Java for Web学习笔记(九四):消息和集群(9)RabbitMQ和消息模式(下)

例子:RPC的实现

这是一个通过AMQP使用RPC的例子,RPC是个同步的处理,需要等待响应。在实际应用需要特别消息,server可能性能很慢,server可能关闭。我们是否一定要使用RPC,是否可以用异步的方式替代。在此,我们只是演示如何利用RabbitMQ提供的消息管理来实现一个RPC。思路如下:

  • RPC Server从一个队列rpc_queue中接收消息,RPC client将请求消息发往rpc_queue队列。
  • 消息的Properties中Correlation-Id带有这个请求的UUID,用于和响应对应。
  • 消息的Properties中Reply-to带有client希望从那个队列中接收这个响应。
  • RPC的调用是同步的,通过BlockingQueue来实现这一个过程。

小例子将简单模拟Fibonacci函数

RPC Server的代码

public class FibonacciRPCServer {
    private static final Logger log = LogManager.getLogger();
    private static final String RPC_QUEUE_NAME = "rpc_queue";

    private Connection connection = null;
    private Channel channel = null;

    public FibonacciRPCServer() throws IOException, TimeoutException{
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("191.8.1.107");
        factory.setUsername("test");
        factory.setPassword("123456");        
        connection = factory.newConnection();
        channel = connection.createChannel();
    }

    public void open() throws IOException {            
        channel.queueDeclare(RPC_QUEUE_NAME, false, false, false, null);
        channel.basicQos(1);
        log.info(" [x] Awaiting RPC requests");

        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
                    throws IOException {
                try {
                    BasicProperties replyProps = new BasicProperties.Builder()
                            .correlationId(properties.getCorrelationId()).build();
                    String message = new String(body,"UTF-8");
                    int n = Integer.parseInt(message);
                    log.info(" [.] fib(" + message + ")");
                    String response = String.valueOf(fib(n));
                    channel.basicPublish( "", properties.getReplyTo(), replyProps, response.getBytes("UTF-8"));
                } finally {
                    channel.basicAck(envelope.getDeliveryTag(), false);
                }

            }

        };

        channel.basicConsume(RPC_QUEUE_NAME, false, consumer); // 需要应答的    
    }

    public void close(){        
        try {
            if(channel != null)
                channel.close();
        } catch (IOException | TimeoutException e) {
            e.printStackTrace();
        }
        try{
            if(connection != null)
                connection.close();
        }catch (IOException e) {
            e.printStackTrace();
        }        
    }

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

RPC Client的代码

public class FibonacciRPCClient {
    private static final Logger log = LogManager.getLogger();
    private Connection connection;
    private Channel channel;
    private String requestQueueName = "rpc_queue";
    private String replyQueueName;

    public FibonacciRPCClient() throws IOException, TimeoutException{
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("191.8.1.107");
        factory.setUsername("test");
        factory.setPassword("123456");
        connection = factory.newConnection();
        channel = connection.createChannel();

        replyQueueName = channel.queueDeclare().getQueue();
    }

    public String call(String message) throws UnsupportedEncodingException, IOException, InterruptedException{
        String corrId = UUID.randomUUID().toString();
        BasicProperties props = new BasicProperties.Builder()
                .correlationId(corrId).replyTo(replyQueueName).build();
        channel.basicPublish("", requestQueueName, props, message.getBytes("UTF-8"));

        final BlockingQueue<String> response = new ArrayBlockingQueue<String>(1);

        channel.basicConsume(replyQueueName, true, new DefaultConsumer(channel){

            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
                    throws IOException {
                if (properties.getCorrelationId().equals(corrId)) {
                    response.offer(new String(body, "UTF-8"));
                }
            }

        });
        return response.take();
    }

    public void close(){        
        // ... 略 ...关闭channel和connection
    }
}

上面,我们注意到

BasicProperties props = new BasicProperties.Builder().correlationId(corrId).replyTo(replyQueueName).build();

我们看一看抓包:

相关链接: 我的Professional Java for Web Applications相关文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值