如何在 rabbitmq 中合并频道?
Posted
技术标签:
【中文标题】如何在 rabbitmq 中合并频道?【英文标题】:How can I pool channels in rabbitmq? 【发布时间】:2012-05-09 02:25:30 【问题描述】:我一直在尝试共享线程之间的连接,并且仅在创建线程时才打开通道,但经过更多研究后,我想我也想尝试connection pooling
。我怎样才能在rabbitmq上做到这一点?或者这是我可以普遍应用的一般想法?我的目标是生成 X 个线程,然后让它们不必打开新通道(这需要在客户端和服务器之间建立循环)。
由于线程是它们自己的类,我不确定是否需要将池放在产生线程的类本身或它们去哪里?我还有多种类型的线程我想共享这些连接之间(不仅仅是一个)。这可能吗?
只是给你一个大致的概念,这里是连接/通道在 rabbitmq 中是如何建立的:
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel(); //I want to share several of these between threads
【问题讨论】:
【参考方案1】:您只需要一个Channel
对象池,您的线程可以从中提取。
Apache commons 实际上已经有一个通用的ObjectPool
你可以使用。
接口的javadoc可以在这里找到:http://commons.apache.org/pool/api-1.6/org/apache/commons/pool/ObjectPool.html
可以在此处找到其中一种预构建实现的 javadoc:http://commons.apache.org/pool/api-1.6/org/apache/commons/pool/impl/GenericObjectPool.html
使用它的教程可以在这里找到:http://commons.apache.org/pool/examples.html
如果这对于您的简单需求来说过于复杂,那么您真正需要做的就是编写一个管理一组Channel
对象的类,允许线程检查它们并将它们返回到池中,并使用适当的同步以防止两个线程获取相同的Channel
【讨论】:
谢谢,我会研究它以了解更多信息,但是对象池是否可以在其他类之间共享?假设我有一个上传的类和一个下载的类,两者都可以使用来自同一个对象池的频道吗? @Lostsoul - 我已经有一段时间没有和兔子打交道了,但是如果Channel
类既用于生产又用于消费,那么是的。
我明白,我的意思是多个类可以访问同一个对象池,还是我需要为每个要使用它的类创建对象池?
抱歉,误解了 - 池的目的是让您的所有类都使用它的相同实例,是的。实现这一点的一般方法是通过依赖注入;让池成为您传递给其他对象的构造函数的东西之一。如果这不可能,您可以将池设置为单例,但最好是前者。
我认为您需要小心重用频道。如果出现错误(例如,您发布到一个不存在的交易所),那么该频道在此之后将毫无用处。它不应该被返回到池中,因为它不能用于进一步的操作,甚至可以无限期地阻塞你的线程。【参考方案2】:
您也可以使用ThreadLocal 对象,以防您使用频道。
RabbitMQ 建议您在每个线程中使用通道,这将是完美的匹配。
示例代码:
private final ThreadLocal<Channel> channels = new ThreadLocal<>();
...
Channel channel = channels.get();
if (channel == null)
channel = connection.createChannel();
channels.set(channel);
无需关闭通道,因为当连接关闭时它们会被您的应用程序关闭。
但是,如果您大量创建新线程,则此解决方案可能不适合您,因为这将分配许多永远不会关闭的新通道。但如果你这样做,你可能做错了什么。
【讨论】:
以上是关于如何在 rabbitmq 中合并频道?的主要内容,如果未能解决你的问题,请参考以下文章