RabbitMQ使用场景练习:RPC(七)

来源:互联网 发布:js简单相册 编辑:程序博客网 时间:2024/05/29 07:18
  • RPC,同步消息
     RabbitMQ默认的consumer为异步监听,RPC应用需要实现consumer的同步,可以使用QueueingConsumer(继承与DefaultConsumer,定义了一个堵塞队列LinkedBlockingQueue)实现同步 
     实际上就是服务端、客户端各定义一个消息队列,相互发送消息,客户端发送消息后同步等待结果返回 

  • 注意要点

发送消息时指定回复队列、corrId
Java代码  收藏代码
  1. //发送消息,指定回复消息所在队列  
  2. BasicProperties props=new BasicProperties.Builder().correlationId(corrId).replyTo(queueName).build();  
  3. channel.basicPublish("""rpc_queue", props, SerializationUtils.serialize(mes));  

监听队列,等待服务端反馈(堵塞)
Java代码  收藏代码
  1. //监听队列,接收服务端回复消息  
  2. while(true){  
  3.     QueueingConsumer.Delivery delivery=consumer.nextDelivery();//堵塞     
  4.     //do something  
  5.     break;  
  6. }  

服务端接收消息处理后回写处理结果
Java代码  收藏代码
  1. channel.basicPublish("", properties.getReplyTo() ,new BasicProperties.Builder().correlationId(properties.getCorrelationId()).build(),   
  2.                         SerializationUtils.serialize("response:"+mes));  

服务端开启手动应答
Java代码  收藏代码
  1. //关闭自动应答机制,默认开启;这时候需要手动进行应该  
  2. channel.basicConsume("rpc_queue"false, consumer);  
  3. channel.basicAck(envelope.getDeliveryTag(), false);  

限制服务端最大处理量
Java代码  收藏代码
  1. channel.basicQos(1);  

  • RPC服务端

Java代码  收藏代码
  1. package com.demo.mq.rabbitmq.example06;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.Serializable;  
  5.   
  6. import org.apache.commons.lang3.SerializationUtils;  
  7.   
  8. import com.demo.mq.rabbitmq.MqManager;  
  9. import com.rabbitmq.client.AMQP;  
  10. import com.rabbitmq.client.AMQP.BasicProperties;  
  11. import com.rabbitmq.client.Channel;  
  12. import com.rabbitmq.client.Connection;  
  13. import com.rabbitmq.client.Consumer;  
  14. import com.rabbitmq.client.DefaultConsumer;  
  15. import com.rabbitmq.client.Envelope;  
  16.   
  17. /** 
  18.  * RPC服务端 
  19.  * @author sheungxin 
  20.  * 
  21.  */  
  22. public class RPCServer{  
  23.   
  24.     /** 
  25.      * RPC服务端,声明一个服务处理队列,接收消息处理后,把结果回写给客户端 
  26.      * 需要开启手动应答机制,确保服务执行完成 
  27.      * @param object 消息主体 
  28.      * @throws IOException 
  29.      */  
  30.     public static void sendAToB(Serializable object) throws Exception{  
  31.         Connection conn=MqManager.newConnection();  
  32.         Channel channel=conn.createChannel();  
  33.         channel.queueDeclare("rpc_queue"falsefalsefalsenull);  
  34.         channel.basicQos(1);  
  35.           
  36.         Consumer consumer=new DefaultConsumer(channel){  
  37.             @Override  
  38.             public void handleDelivery(String consumerTag,Envelope envelope,AMQP.BasicProperties properties,byte[] body) throws IOException{  
  39.                 String mes=SerializationUtils.deserialize(body);  
  40.                 System.out.println(envelope.getRoutingKey()+":Received :'"+mes+"' done");  
  41.                 //接收到消息后,向发送方回写消息:指定发送方所在队列(properties.getReplyTo())、correlationId  
  42.                 channel.basicPublish("", properties.getReplyTo() ,   
  43.                         new BasicProperties.Builder().correlationId(properties.getCorrelationId()).build(),   
  44.                         SerializationUtils.serialize("response:"+mes));  
  45.                 channel.basicAck(envelope.getDeliveryTag(), false);  
  46.             }  
  47.         };  
  48.         //关闭自动应答机制,默认开启;这时候需要手动进行应该  
  49.         channel.basicConsume("rpc_queue"false, consumer);  
  50.         System.out.println("*********8");  
  51.     }  
  52.       
  53.     public static void main(String[] args) throws Exception {  
  54.         sendAToB("Hello World !");  
  55.     }  
  56. }  

  • RPC客户端

Java代码  收藏代码
  1. package com.demo.mq.rabbitmq.example06;  
  2.   
  3. import java.util.UUID;  
  4.   
  5. import org.apache.commons.lang3.SerializationUtils;  
  6.   
  7. import com.demo.mq.rabbitmq.MqManager;  
  8. import com.rabbitmq.client.AMQP.BasicProperties;  
  9. import com.rabbitmq.client.Channel;  
  10. import com.rabbitmq.client.Connection;  
  11. import com.rabbitmq.client.QueueingConsumer;  
  12.   
  13. /** 
  14.  * RPC客户端 
  15.  * @author sheungxin 
  16.  * 
  17.  */  
  18. @SuppressWarnings("deprecation")  
  19. public class RPCClient {  
  20.       
  21.     /** 
  22.      * RPC客户端:向服务端处理队列发送消息,发送时指定correlationId、回复队列名称,同时在回复队列上建立consumer,进行监听接收回复消息 
  23.      * @param mes 
  24.      * @throws Exception 
  25.      */  
  26.     public static String call(String mes) throws Exception{  
  27.         String response=null;  
  28.         Connection conn=MqManager.newConnection();  
  29.         Channel channel=conn.createChannel();  
  30.         //创建一个临时队列,用于接收回复消息  
  31.         String queueName=channel.queueDeclare().getQueue();  
  32.         QueueingConsumer consumer=new QueueingConsumer(channel);  
  33.         channel.basicConsume(queueName, true, consumer);  
  34.           
  35.         String corrId=UUID.randomUUID().toString();  
  36.         //发送消息,指定回复消息所在队列  
  37.         BasicProperties props=new BasicProperties.Builder().correlationId(corrId).replyTo(queueName).build();  
  38.         channel.basicPublish("""rpc_queue", props, SerializationUtils.serialize(mes));  
  39.           
  40.         //监听队列,接收服务端回复消息  
  41.         while(true){  
  42.             QueueingConsumer.Delivery delivery=consumer.nextDelivery();  
  43.             if(delivery.getProperties().getCorrelationId().equals(corrId)){  
  44.                 response=SerializationUtils.deserialize(delivery.getBody());  
  45.                 break;  
  46.             }  
  47.         }  
  48.         return response;  
  49.     }  
  50.       
  51.     public static void main(String[] args) throws Exception {  
  52.         System.out.println(call("hello world"));  
  53.         System.out.println("waiting for rpc is over");  
  54.     }  
  55.   
  56. }  
0 0
原创粉丝点击