RabbitMQ Java API:我想对RPC调用使用basicGet()。能不能让它挡住?它能被打断吗?

RabbitMQ Java API:我想对RPC调用使用basicGet()。能不能让它挡住?它能被打断吗?,rabbitmq,Rabbitmq,我对RabbitMQ相当陌生,并且开始了一个以相当老式的“RPC”模式使用RabbitMQ的项目。因此,我在“服务器”端尝试类似的方法: 我的问题是:等待basicGet()的线程能否被中断?如果是,会发生什么(InterruptedException未声明)。它意识到这不是一个很好的模式,但我只想找到一种干净地关闭服务的方法 更新:一条注释表示basicGet()根本不阻塞,如果队列为空,则立即返回。如果是这样的话,让我把我的问题修改得更精确一些:我如何等待队列中的消息并在超时的情况下检索它

我对RabbitMQ相当陌生,并且开始了一个以相当老式的“RPC”模式使用RabbitMQ的项目。因此,我在“服务器”端尝试类似的方法:

我的问题是:等待basicGet()的线程能否被中断?如果是,会发生什么(InterruptedException未声明)。它意识到这不是一个很好的模式,但我只想找到一种干净地关闭服务的方法

更新:一条注释表示basicGet()根本不阻塞,如果队列为空,则立即返回。如果是这样的话,让我把我的问题修改得更精确一些:我如何等待队列中的消息并在超时的情况下检索它

更新2:在对rabbitmq邮件列表进行实验并提出问题后,我得出结论,这不能直接完成。这根本不是你在RabbitMQ中做事的方式。相反,您可以使用Channel.basicConsume()启动使用者线程池,并等待调用处理程序方法。可以通过让您的消费者发布到同步队列或类似的东西,并让您的前台线程等待,来间接地执行此操作,但请注意,这会破坏basicConsume()提供的自动缩放功能,也会使正确确认所有请求变得更加困难,并且还创建了额外的消息缓冲,这使得很难遵守basicQos()调用设置的QOS语义

还应注意的是,一旦您走上basicConsume()路线,消费者可能会被打断。这是这样做的:

// This starts a background thread pool
String consumerTag = channel.basicConsume(consumer);
...
// Shutdown the consumer thread pool
channel.basicCancel(consumerTag);

更新3:见最后一个答案。RabbitMQ附带了一个工作出色的RpcClient类。

basicGet
不会阻塞,它会立即返回(在网络往返之后),如果队列中没有消息,则返回null。因此不需要中断线程。

RabbitMQ java API附带了一个非常好的RPCClient实现,名为(毫不奇怪)RPCClient。用它!我做了一个

我突然想到服务器本身可以将一个“毒药包”发布到它自己的队列并检查它。好办法?对于非持久性队列似乎可以,但对于持久性队列或共享队列则不太好。这不是一个坏主意。我将让Java客户机维护人员看看这个问题。PS-RabbitMQ团队监视并有时只回答有关StackOverflow的问题。我在一些RabbitMQ示例中看到了“毒药包”技术,用于告诉服务队列的输入已到达末尾,它们现在可以退出。如果您启动在生命周期有限的队列上运行的服务,这可能会很有用。但不是为了在同一过程中打断特定消费者。这最好通过Channel.basicCancel()完成。如果是这种情况,如何等待消息并检索它(可选超时)?没有AMQP方法可以做到这一点。实现这一点的一种方法是向
basicConsume
注册消费者,在消费者中使用
BlockingQueue
将传入消息排队,然后
在循环中轮询
BlockingQueue
。恐怕你会说:-)好的,即使我不喜欢答案,我也会将其标记为已回答。
basicGet不会阻止
。它似乎无限期地阻塞,或者至少在
AMQPChannel.\u rpcTimeout
的持续时间内阻塞,默认为
NO\u RPC\u TIMEOUT
。如果设置了超时,它似乎被包装在一个
ChannelContinuationTimeoutException
中,我仍在跟踪从那里发生的事情。@drobert这不是正常的行为,
basicGet
应该比网络往返多一点,所以我怀疑连接或通道有问题。请将您的问题和其他信息(RabbitMQ和客户端的版本、日志、复制步骤)发布到,以便我们进一步调查。
// This starts a background thread pool
String consumerTag = channel.basicConsume(consumer);
...
// Shutdown the consumer thread pool
channel.basicCancel(consumerTag);