繁体   English   中英

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

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

由于通道不是线程安全的,我可以在发布之前同步通道实例,也可以在每次需要时创建一个通道并关闭它。

但在我看来,由于锁定或创建和销毁通道的成本,它们都没有良好的性能。

那么我应该如何以高 tps 向rabbitmq 发布消息? 对此有何好评?

所以,第一件事。 通道不是连接。 在 RabbitMQ 中,通道与应用程序会话相同,而连接代表与服务器的底层 TCP 会话。 这个答案很好地解释了其中的一些。

TCP 会话的创建成本很高,因此它们的生命周期往往在任何特定工作线程的生命周期之外。 创建频道非常便宜 - 服务器所做的就是为您的频道标识符分配一个整数,然后您就有了一个新频道。

RabbitMQ 上的大多数操作在失败时都会关闭通道。 这样做是因为这样做没有实际后果。 他们是否会关闭底层连接,这会给应用程序带来很多问题。

设计指南

  1. 如果您确实有很多处理正在进行,则池化适用于连接。 关于如何做到这一点的讨论真的超出了我在简短回答中所能提供的。

  2. 池化绝对不适合频道。 通道是一种轻量级构造,旨在具有短暂的生命周期。 如果它的持续时间超过一两次发布,那就太好了。 但是您应该预料到,每次尝试操作时,都有可能会失败并关闭通道。 这不会关闭底层连接,但必须重新建立新通道才能对代理执行任何操作。

  3. 消费者生命周期与渠道相关。 当通道关闭时,附加的消费者也将关闭。 设计您的消费者对象(工作线程),以便在发生这种情况时能够获得连接并创建新通道,然后重新订阅自己。

  4. 避免跨线程共享通道。 一个线程=一个通道。

  5. 虽然我对 Java 客户端没有任何特别的经验,但我认为锁不是必需的,而且我当然希望实现不会做一些奇怪的事情来使 Channels 成为轻量级以外的任何东西。

  6. 如果您正在编写自己的协议实现库(不是必需的,但如果您需要细粒度控制也不是一个坏主意),请分配一个线程来管理每个connection 不要并行读取和写入 TCP 套接字,否则会破坏协议。

  7. 关于 Java 客户端,我认为您可以假设通道操作(读取和写入等)不是线程安全的,这就是您想要坚持一个线程/一个通道范例的原因。 我认为您可以假设创建通道(连接操作)是线程安全的。

你应该使用游泳池。

例如,使用Apache 的通用对象池并提供用于打开、关闭和检查连接的实现。 当你需要发布一条消息时,你从池中借用一个通道,使用它,然后返回它。

暂无
暂无

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

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