Java使用RabbitMQ(九)--RPC

首先声明:
RPC调用会增加系统复杂度以及调试难度,
容易使代码混乱,系统缓慢。

尽量避免使用RPC,转而使用异步管道替代。

rabbitMQ实现的RPC主要流程:

  1. 客户端启动后,创建一个匿名唯一的回调队列
  2. 对于一个RPC请求,客户端发送一个消息和2个属性,一个是replyto用来设置回调队列,另一个是correlationId,每个请求的值都是唯一的
  3. RPC worker(也是被调用的服务方)从请求队列中获取值,每出现一个请求,就处理它,并把结果发送到回调队列返回给 客户端。使用replyto字段
  4. 客户端在回调队列中等待结果,检查correlationId,符合条件的返还给应用。
    这里写图片描述

实现代码(服务方):

public static void main(String[] args) {
        try(Connection connection=getConnection("guest","guest","localhost",5672,"/");
            Channel channel=connection.createChannel()) {

            channel.queueDeclare(queueName, 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, 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) {
                            System.out.println(this.getClass().getName());
                            this.notify();
                        }
                    }
                }

                private int fib(int n) {
                    if (n == 0) return 0;
                    if (n == 1) return 1;
                    return fib(n-1) + fib(n-2);
                }
            };


            channel.basicConsume(queueName, false, consumer);

            while (true){
                synchronized (consumer){
                    consumer.wait();
                }

            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

客户端:

public static void main(String[] args) {

        try (Connection connection = getConnection("guest", "guest", "localhost", 5672, "/");
            Channel channel = connection.createChannel()) {

            String r=call("5",channel,"rpc_queue");
            System.out.println(r);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }


    }
    public static String call(String message,Channel channel,String requestQueueName) throws IOException, InterruptedException {
        String replyQueueName=channel.queueDeclare().getQueue();

        final String corrId= UUID.randomUUID().toString();
        AMQP.BasicProperties properties=new AMQP.BasicProperties.Builder().correlationId(corrId)
                .replyTo(replyQueueName)
                .build();
        channel.basicPublish("",requestQueueName,properties,message.getBytes("utf-8"));

        final BlockingQueue<String> response=new ArrayBlockingQueue<String>(1);
        channel.basicConsume(replyQueueName, true, new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String s, Envelope envelope, AMQP.BasicProperties basicProperties, byte[] bytes) throws IOException {
                if (properties.getCorrelationId().equals(corrId)){
                    response.offer(new String(bytes,"utf-8"));
                }
            }
        });
        return response.take();
    }

猜你喜欢

转载自blog.csdn.net/ljz2016/article/details/79990022
今日推荐