前言
rabbitmq提供了request/reply模式,通过这种模式可以比较轻松的实现rpc,我们可以拿到消费者的返回,通过replytimeout设置超时时间,如果超时返回null。
一、普通request/response模式
- client将消息传递个消息服务,放入队列,消息头中包含reply_to(用于接收消息的排他队列),correlation_id(唯一的,与请求相关);
- server通过队列拿到消息,将消息放到名字为reply_to队列(可以是临时的,可以是持久的)
- 客户端从reply_to队列中拿到消息,通过correlation_id判断是哪个请求。
如果reply队列采用临时队列,消息服务会有创建队列删除队列的操作,对性能消耗比较大,特别是集群环境下,创建队列必须经过所有节点的同意。
用持久的reply队列,如果客户端不是持久的管理起来比较麻烦。
二、RabbitMQ Direct reply-to
RabbitMQ3.4.0开始支持direct reply-to,从Spring AMQP 1.4.1开始,如果没指定reply接收队列(或者接收队列名不是amq.rabbitmq.reply-to),direct reply-to是默认的使用。
简单的说就是在普通request/response模式基础上,去掉了reply队列的使用,但也不是server直接回复client,消息也经过了channel、消息服务节点。
//超时时间
rabbitTemplate.setReplyTimeout(3000);
//唯一id
rabbitTemplate.setUserCorrelationId(true);
User user=new User();
user.setAge(1);
user.setName("heelo");
// CorrelationData correlationData=new CorrelationData(UUID.randomUUID().toString());
String id=UUID.randomUUID().toString();
System.out.println("cd:"+id);
MessageProperties messageProperties = new MessageProperties();
messageProperties.setContentType("application/json");
messageProperties.setCorrelationId(id);
Message message=new Message(mapper.writeValueAsBytes(user),messageProperties);
// IntStream.range(0,100).forEach(arg ->{
Message reply =rabbitTemplate.sendAndReceive("test.exchange","directKey2", message);
System.out.println("reply:"+reply);
AsyncRabbitTemplate
@Bean
public AsyncRabbitTemplate asyncRabbitTemplate (RabbitTemplate rabbitTemplate){
return new AsyncRabbitTemplate(rabbitTemplate);
}
User user=new User();
user.setAge(1);
user.setName("heelo");
String id= UUID.randomUUID().toString();
System.out.println("cd:"+id);
MessageProperties messageProperties = new MessageProperties();
messageProperties.setContentType("application/json");
messageProperties.setCorrelationId(id);
Message message=new Message(mapper.writeValueAsBytes(user),messageProperties);
AsyncRabbitTemplate.RabbitMessageFuture reply =asyncRabbitTemplate.sendAndReceive("test.exchange","directKey", message);
reply.addCallback(new SuccessCallback<Message>() {
@Override
public void onSuccess(Message result) {
System.out.println("receive body:"+new String(result.getBody()));
}
}, new FailureCallback() {
@Override
public void onFailure(Throwable ex) {
ex.printStackTrace();
}
});
//reply.get()