goodboy / tractor

A distributed, structured concurrent runtime for Python (and friends)
GNU Affero General Public License v3.0
258 stars 12 forks source link

Alternative IPC and messaging transports #136

Open carlosplanchon opened 3 years ago

carlosplanchon commented 3 years ago

Goal: To integrate a UDP based transport protocol in order to improve resiliency and latency for multi-host IPC use cases.


NOTE LOTS OF EDITS by @goodboy (mostly summarized from below comments).


Here are the main few protocols which have caught our attenion:




goodboy commented 3 years ago

An interesting protocol I recently started reading about is QUIC developed at google. It's branded as a multiplexed-UDP: a low latency TCP replacement and it's being slowly standardized and introduced to http infra on the internet.

I'm actually pretty interested in the semantics of QoS / cancellation of sub-streams within connections since with trio we can definitely stick to the one-task-per-stream pattern easily.

Python sans-io implementation aioquic has asyncio support using protocols, so we'll need to figure an alt to that for trio.

Here's a list of uses / example code:

goodboy commented 3 years ago

@ryanhiebert it supposedly is sans-io as per:

Both the QUIC and the HTTP/3 APIs follow the "bring your own I/O" pattern, leaving actual I/O operations to the API user. This approach has a number of advantages including making the code testable and allowing integration with different concurrency models.

Maybe I've misunderstood detailed semantics of sans though.

There's an asyncio backend: https://github.com/aiortc/aioquic/tree/main/src/aioquic/asyncio

ryanhiebert commented 3 years ago

That's cool. Weird name for a sans-io package. So I guess we'd have to write the trio backend.

goodboy commented 3 years ago

Some further QUIC resources.

From the wikipedia:

QUIC uses UDP as its basis, which does not include loss recovery. Instead, each QUIC stream is separately flow controlled and lost data retransmitted at the level of QUIC, not UDP. This means that if an error occurs in one stream, like the favicon example above, the protocol stack can continue servicing other streams independently. This can be very useful in improving performance on error-prone links, as in most cases considerable additional data may be received before TCP notices a packet is missing or broken, and all of this data is blocked or even flushed while the error is corrected. In QUIC, this data is free to be processed while the single multiplexed stream is repaired.[19]

In short the protocol is implemented in user space meaning the stack needs to be fast and likely written in a faster language then python. There's a rust implementation quiche we may be able to bind to somewhat fluidly using pyO3. Some further posts from cloudfare:

goodboy commented 3 years ago

Dropping this little project: https://github.com/lithdew/reliable

goodboy commented 2 years ago

Linking this with https://github.com/python-trio/trio/pull/2047!

goodboy commented 1 year ago

Linking to #109 which includes localhost only options. we should probably break up the set of multi-host vs. local host options for investigation by some eager lurkerz 🏄🏼