如何检测基于警报的阻塞RabbitMQ生产者?

时间:2013-01-17 19:13:27

标签: rabbitmq blocking alarm producer-consumer

我有一个生产者向RabbitMQ交换机发送持久消息。如果RabbitMQ内存或磁盘超过水印阈值,RabbitMQ将阻止我的生产者。文档说它停止从套接字读取,并暂停心跳。

我想要的是在生产者代码中知道我被阻止的方法。目前,即使启用了心跳,一切都会永远停顿。我想收到某种异常,以便我知道我已被阻止,我可以警告用户和/或采取其他行动,但我找不到任何方法来做到这一点。我正在使用Java和C#客户端,并且两者都需要此功能。有什么建议?感谢。

2 个答案:

答案 0 :(得分:0)

很抱歉告诉你但是使用RabbitMQ(至少2.8.6)这是不可能的: - (

有类似的问题,其中心是在连接被阻止时尝试建立频道。结果与您遇到的结果相同。

我对RabbitMQ C#.Net Library的实际核心进行了一些调查,发现问题的根本原因是它进入无限阻塞状态。

您可以在此处查看有关RabbitMQ邮件列表的更多详细信息:

http://rabbitmq.1065348.n5.nabble.com/Net-Client-locks-trying-to-create-a-channel-on-a-blocked-connection-td21588.html

一个建议(我们没有实现)是在一个线程内部进行工作,并让一些其他组件管理超时并在超出线程时终止线程。我们接受了风险: - (

答案 1 :(得分:0)

Rabbitmq使用阻止rpc调用来无限期地侦听回复。

如果您查看Java客户端API,它的作用是:

    AMQChannel.BlockingRpcContinuation k = new AMQChannel.SimpleBlockingRpcContinuation();
    k.getReply(-1);

现在-1在参数块中传递,直到收到回复。

好消息是你可以传递你的超时以使其返回。 不好的是你必须更新客户端罐子。

如果您可以这样做,则可以在上述阻塞调用的任何地方传递超时。 代码看起来像:

try {
                    return k.getReply(200);
                } catch (TimeoutException e) {
                    throw new MyCustomRuntimeorTimeoutException("RabbitTimeout ex",e);
                }

在您的代码中,您可以处理此异常并在此事件中执行逻辑。

可能需要此修复的一些相关类将是:

com.rabbitmq.client.impl.AMQChannel
com.rabbitmq.client.impl.ChannelN
com.rabbitmq.client.impl.AMQConnection

仅供参考:我试过这个并且有效。