由于 channel 不是线程安全的,我可以在发布之前同步 channel 实例,也可以在每次需要时创建一个 channel 并关闭它。
但在我看来,由于锁定或创建和销毁 channel 的成本,它们都没有很好的性能。
那么应该如何向高tps的rabbitmq发布消息呢?对此有什么好的赞美吗?
最佳答案
所以,首先要做的是。 channel 不是连接。在 RabbitMQ 中, channel 与应用程序 session 相同,而连接表示与服务器的底层 TCP session 。 This answer很好地解释了其中的一些内容。
TCP session 的创建成本很高,因此它们的生命周期往往在任何特定工作线程的生命周期之外。创建 channel 的成本非常低 - 服务器所做的只是为您的 channel 标识符分配一个整数,然后您就有了一个新 channel 。
RabbitMQ 上的大多数操作在失败时都会关闭 channel 。这样做是因为这样做没有实际后果。他们是否会关闭底层连接,这会给应用程序带来很多问题。
设计指南
如果您确实有大量处理正在进行,则池化适用于连接。关于如何做到这一点的讨论确实超出了我可以在简短回答中提供的范围。
合并绝对不适合 channel 。 channel 是一种轻量级结构,旨在具有短暂的生命周期。如果它持续的时间超过一两次发布,那就太好了。但是你应该预料到每次尝试操作时,它都有可能会失败并关闭 channel 。这不会关闭底层连接,但必须重新建立新 channel 才能对代理执行任何操作。
消费者生命周期与 channel 相关。当 channel 关闭时,附加的消费者也会关闭。将您的消费者对象(工作线程)设计为能够在发生这种情况时获得连接并创建新 channel ,然后重新订阅自己。
避免跨线程共享 channel 。一个线程 = 一个 channel 。
虽然我对 Java 客户端没有任何特别的经验,但我认为锁不是必需的,而且我当然希望实现不会做一些奇怪的事情来使 Channels 除了轻量级。
如果您正在编写自己的协议(protocol)实现库(不是必需的,但如果您需要细粒度控制,这也是一个不错的主意),请分配一个线程来管理每个
连接
。不要并行读取和写入 TCP 套接字,否则会破坏协议(protocol)。关于 Java 客户端,我认为您可以假设 channel 操作(读取和写入等)不是线程安全的,这就是您想要坚持一个线程的原因/一个 channel 范例。我认为您可以假设创建 channel (连接操作)是线程安全的。
关于java - 如何使用高tps、多线程向rabbitmq发布消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48733067/