3 ms·
Problems with these assumptions: - QUIC. Yes, it's UDP, so its connections don't behave the way TCP ones do, but it's still based on IP and UDP connections, so
by peterwwillis 8y ago
Problems with these assumptions:
- QUIC. Yes, it's UDP, so its connections don't behave the way TCP ones do, but it's still based on IP and UDP connections, so it still breaks down under a number of circumstances (rotating backends, mobile clients changing connection types, firewalls/proxies, etc)
- HTTP-based. If you use HTTP, you must accept its warts, like being stateless. Even considering a transport protocol that can multiplex connections, you still need to track all these individual stateless calls. Perhaps a protocol that took care of state might give you some benefits (such as workflowing?)
- Workflow orchestration is just distributed centralized state machines. It shouldn't have much to do with a replacement for REST, because the API isn't necessarily controlling a state machine, and the API (in this case HTTP) isn't stateful anyway...
Why don't we evolve APIs into a sort of language? Why make 4 separate requests (PUT this, GET that, munge it, POST a result, GET to confirm) when you know exactly what you want to do? We can instead build a language or spec where we can shove a variety of instructions (even a "workflow") into a request, let the backend handle the method of accomplishing it for us, and retrieve the result. This can be extended throughout microservice architectures.
The transport protocol is a separate issue. So you want lower latency, and you want less round trips, and you want to survive network interrupt. Design a transport protocol for that (QUIC is a good base). If you want it to survive even more interruption and allow clients to split networks, start looking at intelligent tunnels with advanced routing mechanisms and spread them along the path. But that's a lot more funky than simply replacing TCP.
- acdha 8y ago> - QUIC. Yes, it's UDP, so its connections don't behave the way TCP ones do, but it's still based on IP and UDP connections, so it still breaks down under a number of circumstances (rotating backends, mobile clients changing connection types, firewalls/proxies, etc) Firewall support is a big concern but the other points you mentioned are design goals for QUIC — see section 9 of https://datatracker.ietf.org/doc/draft-ietf-quic-transport/?include_text=1 https://datatracker.ietf.org/doc/draft-ietf-quic-transport/?... (“Connection Migration”): > The use of a connection ID allows connections to survive changes to endpoint addresses (that is, IP address and/or port), such as those caused by an endpoint migrating to a new network. … Not all changes of peer address are intentional migrations. The peer could experience NAT rebinding: a change of address due to a middlebox, usually a NAT, allocating a new outgoing port or even a new outgoing IP address for a flow.
- jimbokun 8y ago"If you use HTTP, you must accept its warts, like being stateless." Being stateless is one of the best things about HTTP, I wouldn't consider it a wart at all. State should be very, very isolated. Ideally, stored in a database somewhere. "Why make 4 separate requests (PUT this, GET that, munge it, POST a result, GET to confirm) when you know exactly what you want to do?" At that point, you are implementing a database with transactions. So expose it over a SQL interface and be done with it (see Cockroach DB). This is solving a very different problem from most REST APIs. Exposing the ability for external customers to run arbitrary transactions against your servers is very dangerous in terms of provisioning, latency, and availability requirements. Unless your business is providing a database as a service.
- cryptonector 8y agoThis is very important. It is absolutely critical to be able to push state out to the client (e.g., using encrypted state cookies, or avoiding state altogether).
- peterwwillis 8y agoState isn't always isolated, and for good reason. Design and operational parameters may dictate state as part of the expected functionality. Sometimes, because of the stateless nature of a protocol, extra work has to be done to constantly re-evaluate an operation in progress to see if it should be terminated early or changed. Since the operation isn't stateful, some other separate component has to act as a sort of babysitter. Then you either have to have the inefficiency of repeated calls, or implement your own pseudo-stateful protocol to wait for some kind of event to be passed up to alert it of a state change. Using the same hammer for every kind of nail is dumb. And no, you don't need a database and transactions just to perform four operations and return a result. Not every transaction will be affected by a change of state in the middle of the transaction. Sometimes transactions are duplicated, or replace a result entirely, and the latest one can win. A transaction in progress can also provide data to another transaction later, and the first transaction can be paused or terminated. We don't see complex interactions like this because the databases and protocols we use have strict separations between their parts, but we don't have to do things this way. The more functionality you surrender to a database, the less flexibility you have in the future, because now your big database is the bottleneck for operations. We need more design paradigms that allow flexible operations, and protocols that can work with such operations to manage transactions by also working with state. I say we "need" this because it seems the state of the art of these systems has languished under proclamations about what we can and can't do, due to assumptions about how we must go about them, and what technology is readily available for use. But we're talking about a new protocol, so we don't have to carry the baggage of those assumptions with us.