• rabbitmq学习(四):利用rabbitmq实现远程rpc调用


    一、rabbitmq实现rpc调用的原理

    ·rabbitmq实现rpc的原理是:客户端向一个队列中发送消息,并注册一个回调的队列用于接收服务端返回的消息,该消息需要声明一个叫做correaltionId的属性,该属性将是该次请求的唯一标识。服务端在接受到消息(在需要时可以验证correaltionId)后,处理消息,并将消息发送到客户端注册的回调队列中。原理图如下:  

      

    二、代码实现

      下面我们将模拟实现一个rpc客户端和rpc服务端。客户端给服务端发送message,服务端收到后处理message,再将处理后的消息返给客户端

      rpc客户端

      

    /**
     * rpc客户端
     */
    public class RpcClient {
        //发送消息的队列名称
        private static final String RPC_QUEUE_NAME = "rpc_queue";
    
        public static void main(String[] args) {
            ConnectionFactory connectionFactory = new ConnectionFactory();
            Connection connection = null;
            Channel channel = null;
            try {
               connection = connectionFactory.newConnection();
               channel = connection.createChannel();
               //创建回调队列
               String callbackQueue = channel.queueDeclare().getQueue();
               //创建回调队列,消费者从回调队列中接收服务端传送的消息
                QueueingConsumer consumer = new QueueingConsumer(channel);
                channel.basicConsume(callbackQueue,true,consumer);
    
                //创建消息带有correlationId的消息属性
                String correlationId = UUID.randomUUID().toString();
                AMQP.BasicProperties basicProperties = new AMQP.BasicProperties().builder().correlationId(correlationId).replyTo(callbackQueue).build();
                String message = "hello rabbitmq";
                channel.basicPublish("",RPC_QUEUE_NAME,basicProperties,message.getBytes());
                System.out.println("RpcClient send message " + message + ", correaltionId = " + correlationId);
    
                //接收回调消息
                while (true){
                    QueueingConsumer.Delivery delivery = consumer.nextDelivery();
                    String receivedCorrelationId = delivery.getProperties().getCorrelationId();
                    if(correlationId.equals(receivedCorrelationId)){
                        System.out.println("RpcClient receive format message " + new String(delivery.getBody(), "UTF-8") + ", correaltionId = " + correlationId);
                        break;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                try {
                    channel.close();
                    connection.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    
        }
    }

       rpc服务端

      

    /**
     * rpc服务器
     */
    public class RpcServer {
        private static final String RPC_QUEUE_NAME = "rpc_queue";
    
        private static String format(String message){
            return "......" + message + "......";
        }
    
        public static void main(String[] args) {
            ConnectionFactory connectionFactory = new ConnectionFactory();
            Connection connection = null;
            try {
                connection = connectionFactory.newConnection();
                Channel channel = connection.createChannel();
                channel.queueDeclare(RPC_QUEUE_NAME,false,false,false,null);
                QueueingConsumer consumer = new QueueingConsumer(channel);
                //声明消费者预取的消息数量
                channel.basicQos(1);
                channel.basicConsume(RPC_QUEUE_NAME,false,consumer);//采用手动回复消息
                System.out.println("RpcServer waitting for receive message");
    
                while (true){
                    //接收并处理消息
                    QueueingConsumer.Delivery delivery = consumer.nextDelivery();
                    String message = new String(delivery.getBody(), "UTF-8");
                    System.out.println("RpcServer receive message " + message);
                    String response = format(message);
                    //确认收到消息
                    channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
    
                    //取出消息的correlationId
                    AMQP.BasicProperties properties = delivery.getProperties();
                    String correlationId = properties.getCorrelationId();
    
                    //创建具有与接收消息相同的correlationId的消息属性
                    AMQP.BasicProperties replyProperties = new AMQP.BasicProperties().builder().correlationId(correlationId).build();
                    channel.basicPublish("",properties.getReplyTo(),replyProperties,response.getBytes());
                }
    
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

       先运行服务端,再运行客户端,结果如下:

      RpcClient

      

      RpcServer

      

     

    代码gitbu地址:https://github.com/wutianqi/rabbitmq-learn.git

    参考资料:https://www.cnblogs.com/LipeiNet/p/5980802.html

  • 相关阅读:
    人工智能深度学习:TensorFlow2.0如何保持和读取模型?
    人工智能深度学习:TensorFlow2.0实现回归问题
    InnoDB存储引擎中的锁
    Spring源码系列8
    Spring源码系列7
    Spring源码系列6
    Spring源码系列5
    Spring源码系列4
    Spring源码系列3
    Spring源码系列2
  • 原文地址:https://www.cnblogs.com/wutianqi/p/10055391.html
Copyright © 2020-2023  润新知