Open lsunsi opened 7 months ago
I think it's really going to depend on you use case. This crate simply implements the protocol.
I think in most use cases, long-lived connections are used for sending and receiving messages, which is probably not the best place to use a connection pool. Because AMQP has all the handshakes for creating Connection
, Session
, and Link
, I don't think the protocol is designed for use cases where short-lived connections are frequently created and dropped. You will likely see a worse performance in such use cases.
The Session
type is more of a grouping of multiple links where messages are multiplexed, and provide some flow control for this group of links, but the state is still stored within each individual link. However, all the AMQP 1.0 message brokers/services don't seem to make much use of the session at all.
If you were to pursue a use case with connection pool, I think anything that gives you a pool of tokio
compatible connection (tokio
's AsyncRead + AsyncWrite
) would work. You can set up an AMQP Connection
directly with a stream using this method open_with_stream
Or if you were thinking about a pool of AMQP Connection
s, I think it's possible with the current API, but I don't think it's the recommended usage. The way you would want to reconnect a link to another connection is essentially the link recovery process, which again is not designed for frequently creating short-lived senders and receivers.
All sessions (and thus their links) that share the same Connection
are multiplexed. I think some simple experimentation is needed to see whether having dedicated connection per sender/receiver or sharing a multiplexed connection with a group of sender/receivers gives the best throughput. In an related issue (https://github.com/minghuaw/azeventhubs/issues/9), the best performance was achieved with dedicated connections for each sender/receiver
Here is a good article explaining the protocol without diving into the 100+ pages long spec (https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-amqp-protocol-guide)
I remember seeing folks from Azure messaging (probably Service Bus) NOT recommending using AMQP as if it is HTTP because there are more handshakes. But for long-lived connections, AMQP is more efficient and performant in their context which is comparing using AMQP vs REST API with Service Bus
Wow what an amazing answer. Absolutely, this makes sense. I'll read the documentation and get to know better. Thanks a lot!
I might report back to this issue if I get more concrete and useful information. I'll use this library to setup a big project I have with activemq artemis, so I might have some insights after that!
Feel free to keep this issue open for questions and feedback. There are probably use cases that I had not considered, and I will be more than happy to help you if you need some new feature for your use case
Seriously, thank you! This interaction was unexpectedly wholesome and improved on my Saturday haha
@minghuaw One more question for you. I'm gonna use this library in an application with about 20 senders and 20 receivers at all times. Should I create a single session to attach all of them, or one by one? I know this question is more about AMQP 1.0 then the library, but I'm having trouble understanding the positioning of the session concept within it all.
I would say having one session per sender/receiver would likely be the better option (if memory is not too limited). This really comes down to two reasons.
The shared state as well as the channels to the link are all stored in HashMaps in the session event loop, but it shouldn't be a big problem unless you have a really limited memory to work with.
@minghuaw Thanks again for the quick response. Another thing, the Connection and Session objects are not related (lifetime wise) with the Receiver/Sender ones. If I have a Sender, do I have to keep the Connection and Session objects alive so it works, or it would work even independently of the previous objects?
The reason I ask is because I don't know whether to hold the Session alongside the Sender in my structs or not. Sorry for the newb questions.
@minghuaw Thanks again for the quick response. Another thing, the Connection and Session objects are not related (lifetime wise) with the Receiver/Sender ones. If I have a Sender, do I have to keep the Connection and Session objects alive so it works, or it would work even independently of the previous objects?
The reason I ask is because I don't know whether to hold the Session alongside the Sender in my structs or not. Sorry for the newb questions.
You would want to keep the connection and session variables until you close the links(sender/receiver), and you would want to close the session before closing the connection. This is an unfortunate design choice. Channels are used to transmit messages between connection, session and links, and the channels themselves don't carry explicit lifetimes. Another problem is if explicit lifetime was introduced to links, it would make spawning multiple sender and receiver really convoluted because spawn generally requires something that has 'static lifetime
Yeah this makes sense. Another last question, and I'm sorry to keep bothering you. Is it ok to keep Sender/Receiver around for long times after initialization?
I think the flow of my program will be something like, spawning the 20 session and senders/receivers at boot time, keeping all structs alive while we are at it, and just keep using them for as long as the software runs.
That should be fine on the library side. However, you would probably want to check if there's any settings regarding the idle time on your message broker (this may also be different for sender and receiver). For example, i think it's Service Bus or Event Hubs that enforces a 30 mins idle time limit for senders.
It's probably a dumb question, but do I need to have multiple connections for a large application or a single one is enough?
Does the Session concept relate in any way to my question since it can multiplex operations from what I understood?
In case a connection pool make sense, is there any implementation to go with this lib? Would integrating with Deadpool library make sense?