Antti / rust-amqp

AMQP client in pure rust. Corresponds to rabbitmq spec.
MIT License
249 stars 45 forks source link

Tokio support #53

Open pimeys opened 7 years ago

pimeys commented 7 years ago

Hi,

What is the status of the async Tokio support in this library? Any places you need help? This would be super useful for our company in the next six months...

Antti commented 7 years ago

Hi,

I was working at this some time ago, but tokio was changing every day and it was a bit hard to keep up. Also I'm not sure about the whole async model for a client. Are there any good example of clients using tokio? The biggest conceptual problem I have is creating consumers and producers. If one consumer is slow it will block all other consumers and the event loop.

That is because we either receive all frames for all channels and buffer them for the slow consumers (making app eat memory uncontrollably) or blocking all the consumers until the slowest one finishes consuming.

                                               +---> consumer
                                               |
+------------------+        +---------------+  +---> consumer
|     Broker       +------->+ message queue +--+
+------------------+        +---------------+  +---> consumer
                                               |
                                               +---> consumer

So, having this implemented this way, makes async client kind of pointless in terms of performance gains. If we can come up with a consumers design which can be improved by making library asynchronous, then it will make sense spending time on it.

pimeys commented 7 years ago

What about creating one session and one channel per consumer, and if you need more consumers in one application you just create new connections. I read the AMQP spec and I agree we get all the channels through one connection.

But what gains we'd have here: one would be having a Stream for consuming and a Sink for producing, which makes connecting this to other libraries in tokio ecosystem much easier. Also this would nail the problem of closing the consumer, for example with a oneshot channel or tokio signal.

I think the future for consumers is in Tokio, and making this library part of that ecosystem a nice addition.

agentgt commented 7 years ago

I remember the Java Rabbit guys looked at implementing the client with NIO select (aka netty reactor loop style) and if I recall to (@Antti point) the consensus was there would be very little to gain performance wise and might even hurt performance (particularly if you are acking messages).

... but there are some special cases like RPC using the direct-reply-to extension where I can see an async loop being better.

pimeys commented 7 years ago

Hmm, could we then just have an iterator out of the consumer? I'm currently reading through the code if I could make the consumer more useful. It's ok to run it in its own thread and do the async stuff in another thread, but my hacky way of stopping the consumer will not fly that far...

whitfin commented 6 years ago

@agentgt this is a fair point, but I think that there's utility in offering a Tokio interface just for people who need to use futures themselves inside their consumers. As it stands right now (unless I'm mistaken), it's a pain to use something like Hyper inside a consumer because one is futures and the other is not (so there's no Tokio runtime for Hyper).

polachok commented 6 years ago

lapin-futures is an amqp library with future-based api