Java RabbitMQ不';Don’不要选择正确的消费者
我以这里的示例为例,从Java RabbitMQ不';Don’不要选择正确的消费者,java,rabbitmq,Java,Rabbitmq,我以这里的示例为例,从RPCClient添加了一个RPC调用,并添加了一些登录到stdout的内容。因此,当执行第二个调用时,rabbitmq使用具有错误关联id的使用者,这不是预期的行为。这是一个bug还是我出了什么问题 RPC服务器: package com.foo.rabbitmq; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.Connection; import com.rabbitm
RPCClient
添加了一个RPC调用,并添加了一些登录到stdout的内容。因此,当执行第二个调用时,rabbitmq使用具有错误关联id的使用者,这不是预期的行为。这是一个bug还是我出了什么问题
RPC服务器:
package com.foo.rabbitmq;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Envelope;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class RPCServer {
private static final String RPC_QUEUE_NAME = "sap-consume";
private static int fib(int n) {
if (n ==0) return 0;
if (n == 1) return 1;
return fib(n-1) + fib(n-2);
}
public static void main(String[] argv) {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(5672);
Connection connection = null;
try {
connection = factory.newConnection();
final Channel channel = connection.createChannel();
channel.queueDeclare(RPC_QUEUE_NAME, false, false, false, null);
channel.basicQos(1);
System.out.println(" [x] Awaiting RPC requests");
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
AMQP.BasicProperties replyProps = new AMQP.BasicProperties
.Builder()
.correlationId(properties.getCorrelationId())
.build();
String response = "";
try {
String message = new String(body,"UTF-8");
int n = Integer.parseInt(message);
System.out.println(" [.] fib(" + message + ")");
response += fib(n);
}
catch (RuntimeException e){
System.out.println(" [.] " + e.toString());
}
finally {
channel.basicPublish( "", properties.getReplyTo(), replyProps, response.getBytes("UTF-8"));
channel.basicAck(envelope.getDeliveryTag(), false);
// RabbitMq consumer worker thread notifies the RPC server owner thread
synchronized(this) {
this.notify();
}
}
}
};
channel.basicConsume(RPC_QUEUE_NAME, false, consumer);
// Wait and be prepared to consume the message from RPC client.
while (true) {
synchronized(consumer) {
try {
consumer.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} catch (IOException | TimeoutException e) {
e.printStackTrace();
}
finally {
if (connection != null)
try {
connection.close();
} catch (IOException _ignore) {}
}
}
}
RPC客户:
package com.bar.rabbitmq;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Envelope;
import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeoutException;
public class RPCClient {
private Connection connection;
private Channel channel;
private String requestQueueName = "sap-consume";
private String replyQueueName;
public RPCClient() throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(5672);
connection = factory.newConnection();
channel = connection.createChannel();
replyQueueName = channel.queueDeclare().getQueue();
}
public String call(String message) throws IOException, InterruptedException {
final String corrId = UUID.randomUUID().toString();
AMQP.BasicProperties props = new AMQP.BasicProperties
.Builder()
.correlationId(corrId)
.replyTo(replyQueueName)
.build();
channel.basicPublish("", requestQueueName, props, message.getBytes("UTF-8"));
final BlockingQueue<String> response = new ArrayBlockingQueue<String>(1);
channel.basicConsume(replyQueueName, true, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
if (properties.getCorrelationId().equals(corrId)) {
System.out.println("Correlation Id" + properties.getCorrelationId() + " corresponds to expected one.");
response.offer(new String(body, "UTF-8"));
} else {
System.out.println("Correlation Id" + properties.getCorrelationId() + " doesn't correspond to expected one " + corrId);
}
}
});
return response.take();
}
public void close() throws IOException {
connection.close();
}
public static void main(String[] argv) {
RPCClient rpc = null;
String response = null;
try {
rpc = new RPCClient();
System.out.println(" [x] Requesting fib(30)");
response = rpc.call("30");
System.out.println(" [.] Got '" + response + "'");
System.out.println(" [x] Requesting fib(40)");
response = rpc.call("40");
System.out.println(" [.] Got '" + response + "'");
} catch (IOException | TimeoutException | InterruptedException e) {
e.printStackTrace();
} finally {
if (rpc != null) {
try {
rpc.close();
} catch (IOException _ignore) {
}
}
}
}
}
package com.bar.rabbitmq;
导入com.rabbitmq.client.ConnectionFactory;
导入com.rabbitmq.client.Connection;
导入com.rabbitmq.client.Channel;
导入com.rabbitmq.client.DefaultConsumer;
导入com.rabbitmq.client.AMQP;
导入com.rabbitmq.client.Envelope;
导入java.io.IOException;
导入java.util.UUID;
导入java.util.concurrent.ArrayBlockingQueue;
导入java.util.concurrent.BlockingQueue;
导入java.util.concurrent.TimeoutException;
公共类RPCClient{
专用连接;
专用信道;
私有字符串requestQueueName=“sap consume”;
私有字符串replyQueueName;
public RPCClient()引发IOException、TimeoutException{
ConnectionFactory工厂=新的ConnectionFactory();
setHost(“localhost”);
工厂设置端口(5672);
connection=factory.newConnection();
channel=connection.createChannel();
replyQueueName=channel.queueDeclare().getQueue();
}
公共字符串调用(字符串消息)引发IOException、InterruptedException{
最后一个字符串corid=UUID.randomUUID().toString();
AMQP.BasicProperties道具=新的AMQP.BasicProperties
.Builder()
.correlationId(corrId)
.replyTo(replyQueueName)
.build();
channel.basicPublish(“,requestQueueName,props,message.getBytes(“UTF-8”);
最终阻塞队列响应=新的ArrayBlockingQueue(1);
channel.basicConsume(replyQueueName,true,新的DefaultConsumer(通道){
@凌驾
public void handleDelivery(字符串consumerTag、信封信封、AMQP.BasicProperties属性、字节[]正文)引发IOException{
if(properties.getCorrelationId().equals(corrId)){
System.out.println(“Correlation Id”+properties.getCorrelationId()+“对应于预期的值”);
报价(新字符串(正文,“UTF-8”);
}否则{
System.out.println(“相关Id”+properties.getCorrelationId()+”与预期的“+corrId”)不对应;
}
}
});
返回响应。take();
}
public void close()引发IOException{
connection.close();
}
公共静态void main(字符串[]argv){
RPCClient rpc=null;
字符串响应=null;
试一试{
rpc=新的RPCClient();
System.out.println(“[x]请求fib(30)”);
响应=rpc.call(“30”);
System.out.println(“[.]得到“+”响应“+””);
System.out.println(“[x]请求fib(40)”;
响应=rpc.call(“40”);
System.out.println(“[.]得到“+”响应“+””);
}捕获(IOException | TimeoutException | InterruptedException e){
e、 printStackTrace();
}最后{
如果(rpc!=null){
试一试{
rpc.close();
}捕获(IOException\u忽略){
}
}
}
}
}
是的,您在教程代码中发现了一个bug。我在这里打开了一个pull请求来修复它,您也可以找到正在发生的事情的解释:
注意:RabbitMQ团队监视并有时只回答有关StackOverflow的问题。是的,您在教程代码中发现了一个bug。我在这里打开了一个pull请求来修复它,您也可以找到正在发生的事情的解释:
注意:RabbitMQ团队监视并有时只回答有关StackOverflow的问题。此示例过于简单:它使用一个队列进行回复。通过发送第二个请求,您向回复注册了一个新的使用者,但第一个请求的使用者仍在侦听,实际上窃取了第二个请求的响应。这就是为什么客户端似乎使用相同的关联ID 我们需要为每个请求使用独占的自动删除队列。此队列将由服务器自动删除,因为在收到响应后,其唯一使用者将取消订阅。这有点复杂,但更接近真实世界的场景
注意,使用RabbitMQ处理回复队列的最佳方法是使用。这使用比实际队列轻的伪队列。我们在教程中没有提到直接回复,以使其尽可能简单,但这是在生产中使用的首选功能。此示例过于简单:它使用一个队列进行回复。通过发送第二个请求,您向回复注册了一个新的使用者,但第一个请求的使用者仍在侦听,实际上窃取了第二个请求的响应。这就是为什么客户端似乎使用相同的关联ID 我们需要为每个请求使用独占的自动删除队列。此队列将由服务器自动删除,因为在收到响应后,其唯一使用者将取消订阅。这有点复杂,但更接近真实世界的场景 注意,使用RabbitMQ处理回复队列的最佳方法是使用。这使用比实际队列轻的伪队列。我们在教程中没有提到直接回复以尽可能简单,但这是在生产中使用的首选功能