vert-x3 / vertx-rabbitmq-client

Vert.x RabbitMQ Service
Apache License 2.0
73 stars 64 forks source link

Only one channel per connection #78

Open amorozow42 opened 5 years ago

amorozow42 commented 5 years ago

As I can see from source code RabbitMQ client creates one channel on connection. While common scenario is to create one channel for consumer. Here is quote from RabbitMQ docs:

Each Channel has its own dispatch thread. For the most common use case of one Consumer per Channel, this means Consumers do not hold up other Consumers. If you have multiple Consumers per Channel be aware that a long-running Consumer may hold up dispatch of callbacks to other Consumers on that Channel.

Yaytay commented 4 years ago

In my synchronous rabbit library I create a map of names to channels for a single connection. Translating that to the vertx library wouldn't be a vast amount of work, but would require overloads of a lot of methods to allow the desired channel name to be passed in. The alternative would be to separate out the channel as a distinct concept, but that's a lot more work and would definitely break the existing API completely.

amorozow42 commented 4 years ago

We need channel pool object.

Yaytay commented 4 years ago

The problem with having a simple pool of channels is that tags are scoped to the channel, so you need to know the channel when acknowledging or confirming. That's why the Rabbit docs recommend making the channels per thread, but that's not really an option in vertx (or anything thread pool based). I found named channels the simpler than tracking the channels from a pool.

amorozow42 commented 4 years ago

Can you provide code sample which demonstrate a usage of named channels?

Yaytay commented 4 years ago

Only for a synchronous client library that is completely different from the vertx lib - that lib has its own Channel class and Connection::getChannel(String name) returns an open channel. To do it for the vertx client without introducing a Channel class would need something like: {code:java} void basicConsumer(String channel, String queue, QueueOptions options, Handler<AsyncResult> resultHandler); {code} With a similar name inserted for all the operations that should be for a channel. Then we'd have to modify the internal call to forChannel to work with the map of channels.

amorozow42 commented 3 years ago

Hello from 2021 :)

Yaytay commented 3 years ago

Hello. In order to approach this we need to come up with a design that works. A simple channel pool is not viable because notifications relate to channels (it wouldn't be possible to track IDs). So we need to know at the time of sending which channel to use. I see two basic ways this could be done, both of which completely break the existing API:

  1. Split the channel out in the API, so the client can explicitly create a channel and then interacts with that channel instead of with the client.
  2. Have named channels.

In my usage I haven't had enough channels to justify the upheaval. How many channels per process are you trying to use?

amorozow42 commented 3 years ago

I want to use separate channel for each consumer. Also there must be separate channel/channels for publishing. Ideally the client should not know anything about this details. When we create new consumer we create new channel underneath.