- RPC,同步消息
实际上就是服务端、客户端各定义一个消息队列,相互发送消息,客户端发送消息后同步等待结果返回
- 注意要点
发送消息时指定回复队列、corrId:
//发送消息,指定回复消息所在队列 BasicProperties props=new BasicProperties.Builder().correlationId(corrId).replyTo(queueName).build(); channel.basicPublish("", "rpc_queue", props, SerializationUtils.serialize(mes));
监听队列,等待服务端反馈(堵塞):
//监听队列,接收服务端回复消息 while(true){ QueueingConsumer.Delivery delivery=consumer.nextDelivery();//堵塞 //do something break; }
服务端接收消息处理后回写处理结果:
channel.basicPublish("", properties.getReplyTo() ,new BasicProperties.Builder().correlationId(properties.getCorrelationId()).build(), SerializationUtils.serialize("response:"+mes));
服务端开启手动应答:
//关闭自动应答机制,默认开启;这时候需要手动进行应该 channel.basicConsume("rpc_queue", false, consumer); channel.basicAck(envelope.getDeliveryTag(), false);
限制服务端最大处理量:
channel.basicQos(1);
- RPC服务端
package com.demo.mq.rabbitmq.example06; import java.io.IOException; import java.io.Serializable; import org.apache.commons.lang3.SerializationUtils; import com.demo.mq.rabbitmq.MqManager; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.AMQP.BasicProperties; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.Consumer; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.Envelope; /** * RPC服务端 * @author sheungxin * */ public class RPCServer{ /** * RPC服务端,声明一个服务处理队列,接收消息处理后,把结果回写给客户端 * 需要开启手动应答机制,确保服务执行完成 * @param object 消息主体 * @throws IOException */ public static void sendAToB(Serializable object) throws Exception{ Connection conn=MqManager.newConnection(); Channel channel=conn.createChannel(); channel.queueDeclare("rpc_queue", false, false, false, null); channel.basicQos(1); Consumer consumer=new DefaultConsumer(channel){ @Override public void handleDelivery(String consumerTag,Envelope envelope,AMQP.BasicProperties properties,byte[] body) throws IOException{ String mes=SerializationUtils.deserialize(body); System.out.println(envelope.getRoutingKey()+":Received :'"+mes+"' done"); //接收到消息后,向发送方回写消息:指定发送方所在队列(properties.getReplyTo())、correlationId channel.basicPublish("", properties.getReplyTo() , new BasicProperties.Builder().correlationId(properties.getCorrelationId()).build(), SerializationUtils.serialize("response:"+mes)); channel.basicAck(envelope.getDeliveryTag(), false); } }; //关闭自动应答机制,默认开启;这时候需要手动进行应该 channel.basicConsume("rpc_queue", false, consumer); System.out.println("*********8"); } public static void main(String[] args) throws Exception { sendAToB("Hello World !"); } }
- RPC客户端
package com.demo.mq.rabbitmq.example06; import java.util.UUID; import org.apache.commons.lang3.SerializationUtils; import com.demo.mq.rabbitmq.MqManager; import com.rabbitmq.client.AMQP.BasicProperties; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.QueueingConsumer; /** * RPC客户端 * @author sheungxin * */ @SuppressWarnings("deprecation") public class RPCClient { /** * RPC客户端:向服务端处理队列发送消息,发送时指定correlationId、回复队列名称,同时在回复队列上建立consumer,进行监听接收回复消息 * @param mes * @throws Exception */ public static String call(String mes) throws Exception{ String response=null; Connection conn=MqManager.newConnection(); Channel channel=conn.createChannel(); //创建一个临时队列,用于接收回复消息 String queueName=channel.queueDeclare().getQueue(); QueueingConsumer consumer=new QueueingConsumer(channel); channel.basicConsume(queueName, true, consumer); String corrId=UUID.randomUUID().toString(); //发送消息,指定回复消息所在队列 BasicProperties props=new BasicProperties.Builder().correlationId(corrId).replyTo(queueName).build(); channel.basicPublish("", "rpc_queue", props, SerializationUtils.serialize(mes)); //监听队列,接收服务端回复消息 while(true){ QueueingConsumer.Delivery delivery=consumer.nextDelivery(); if(delivery.getProperties().getCorrelationId().equals(corrId)){ response=SerializationUtils.deserialize(delivery.getBody()); break; } } return response; } public static void main(String[] args) throws Exception { System.out.println(call("hello world")); System.out.println("waiting for rpc is over"); } }