2

Since channel is not thread safe, I can either synchronize th channel instance before publish or I create a channel each time I need and close it.

But in my opinion neither of them have a good performance due to cost of locking or create and destory channels.

So how should I publish message to rabbitmq with high tps? Any good pratise on this?

JaskeyLam
  • 15,405
  • 21
  • 114
  • 149

2 Answers2

1

So, first thing first. A channel is not a connection. In RabbitMQ, Channels are the same thing as application sessions, whereas a connection represents an underlying TCP session with the server. This answer explains some of that nicely.

TCP sessions are expensive to create, so they tend to have a lifetime outside the lifetime of any particular worker thread. Channels are extremely cheap to create - all the server does is assign you an integer for your channel identifier and you have a new channel.

Most operations on RabbitMQ close a channel when they fail. This is done because there is no practical consequence of doing so. Would they close the underlying connection, that would cause a lot of problems for the app.

Design Guidance

  1. Pooling would be appropriate for connections, if you really have a lot of processing going on. A discussion on how to do this is really beyond what I can provide in a short answer.

  2. Pooling is absolutely not appropriate for channels. A channel is a lightweight construct that is designed to have a transient lifetime. If it lasts longer than one or two publishes, great. But you should expect that every time you try an operation, there is a possibility it will fail and close the channel. This does not close the underlying connection, but a new channel will have to be reestablished to do anything with the broker.

  3. Consumer lifetimes are tied to channels. When the channel closes, the attached consumer is closed too. Design your consumer objects (worker threads) to be able to get a connection and create a new channel when this happens, and then re-subscribe themselves.

  4. Avoid sharing a channel across threads. One thread = one channel.

  5. While I don't have any particular experience with the Java client, I don't believe locks should be necessary, and I would certainly hope that the implementation doesn't do something screwy to make Channels anything other than lightweight.

  6. If you're writing your own protocol implementation library (not necessary, but also not a bad idea if you need fine-grained control), allocate one thread to manage each connection. Don't do reads and writes to the TCP socket in parallel, or you'll break the protocol.

  7. Regarding the Java client, I think you can assume that channel operations (reads and writes, etc.) are NOT thread-safe, which is why you want to stick to one thread/one channel paradigm. I think you can assume that creating channels (a connection operation) is thread-safe.

theMayer
  • 15,456
  • 7
  • 58
  • 90
  • Now I have a pulish tps with larger than 2000 tps, and indeed I am creating channel and destroy it every time I need to publish .But this means if I want to create a chanel and lose it every time I publish, I need to have additional two TCP communication with broker which is a burden to the broker. And now I have already notice that the broker have triggered flow control on my connection, so I am now trying to do anything to make it more efficiency. I guess pooling of channel is a way, isn't it? – JaskeyLam Feb 22 '18 at 02:54
  • No. You have multiple things going on. You do not need to create a channel every time you publish - once a publishing component of your application has a channel, it can be reused until you do something that results in closure. There is no limit on the number of channels per connection. And flow control means you are publishing at a rate too fast for the consumer on the other end (whoever is getting your messages) so that will be a global problem regardless, but those settings are configurable. – theMayer Feb 22 '18 at 04:47
  • 1. But the channel is not thread safe so I either have multiple channels or do synchronization. so in a word, pooling of the channels or using thread local is a good way , isn't it? 2. Is flow control affected by the consume rate? Isn't it only affected by the capability of broker(like Kafka), so do you mean RabbitMQ can not publish massive messages on the broker with slow consumption? – JaskeyLam Feb 22 '18 at 08:09
  • If you’re creating and destroying a new thread each time you need to publish, you’ve probably got bigger problems than I can help you with. – theMayer Feb 22 '18 at 11:36
  • the thread is managed by the fixed trhead pool with 200 fixed size – JaskeyLam Feb 23 '18 at 03:48
0

You should use a pool.

For instance, use Apache's Generic Object Pool and provide an implementation for opening, closing and checking connections. When you need to publish a message, you borrow a channel from the pool, use it, and return it.

Malt
  • 28,965
  • 9
  • 65
  • 105