简体   繁体   English

如何以高 tps、多线程向rabbitmq 发布消息

[英]How to publish messages to rabbitmq with high tps, multithreading

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?那么我应该如何以高 tps 向rabbitmq 发布消息? Any good pratise on this?对此有何好评?

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.在 RabbitMQ 中,通道与应用程序会话相同,而连接代表与服务器的底层 TCP 会话。 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. TCP 会话的创建成本很高,因此它们的生命周期往往在任何特定工作线程的生命周期之外。 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. RabbitMQ 上的大多数操作在失败时都会关闭通道。 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.虽然我对 Java 客户端没有任何特别的经验,但我认为锁不是必需的,而且我当然希望实现不会做一些奇怪的事情来使 Channels 成为轻量级以外的任何东西。

  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 .如果您正在编写自己的协议实现库(不是必需的,但如果您需要细粒度控制也不是一个坏主意),请分配一个线程来管理每个connection Don't do reads and writes to the TCP socket in parallel, or you'll break the protocol.不要并行读取和写入 TCP 套接字,否则会破坏协议。

  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.关于 Java 客户端,我认为您可以假设通道操作(读取和写入等)不是线程安全的,这就是您想要坚持一个线程/一个通道范例的原因。 I think you can assume that creating channels (a connection operation) is thread-safe.我认为您可以假设创建通道(连接操作)是线程安全的。

You should use a pool.你应该使用游泳池。

For instance, use Apache's Generic Object Pool and provide an implementation for opening, closing and checking connections.例如,使用Apache 的通用对象池并提供用于打开、关闭和检查连接的实现。 When you need to publish a message, you borrow a channel from the pool, use it, and return it.当你需要发布一条消息时,你从池中借用一个通道,使用它,然后返回它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM