rabbitmq学习6:RPC

本文介绍了如何使用 RabbitMQ 实现远程过程调用 (RPC)。通过创建客户端和服务端,演示了如何通过设置 reply_to 和 correlation_id 属性来实现请求与响应的匹配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 在《rabbitmq学习2:Work Queues 》中我们已经知道了在多个worker如何分配耗时的任务。如果我现在要在远程的机器上运行然后得到结果,那应当怎么做呢?那就要用到RPC(Remote Procedure Call or RPC )了!

   关于RPC的介绍请参考百度百科里的关于RPC的介绍:http://baike.baidu.com/view/32726.htm#sub32726

   现在来看看来看看Rabbitmq中RPC吧!RPC的工作示意图如下:


   上图中的C代表客户端,S表示服务器端;Rabbitmq中的RPC流程如下:

1、首先客户端发送一个reply_to和corrention_id的请求,发布到RPC队列中;

2、服务器端处理这个请求,并把处理结果发布到一个回调Queue,此Queue的名称应当与reply_to的名称一致

3、客户端从回调Queue中得到先前corrention_id设定的值的处理结果。如果碰到和先前不一样的corrention_id的值,将会忽略而不是抛出异常。

 

  对于上面所提到的回调Queue中的消费处理使用的是BasicProperties类;而消息 属性在AMQP的协议中规定有14个;而很多大部分我们没有用到。常用的几个属性有:

English代码   收藏代码
  1. Message properties  
  2. The AMQP protocol predefine a set of 14 properties that go with a message. Most of the properties are rarely used, with the exception of the following:  
  3.   
  4. delivery_mode: Marks a message as persistent (with a value of 2) or transient (any other value). You may remember this property from the second tutorial.   
  5. content_type: Used to describe the mime-type of the encoding. For example for the often used JSON encoding it is a good practice to set this property to: application/json.   
  6. reply_to: Commonly used to name a callback queue.   
  7. correlation_id: Useful to correlate RPC responses with requests.   

 

 delivery_mode : 标记消息是持久性消息还是瞬态信息。在前面的“Work Queue”中我们已经提到过;   

  content_type : 用来描述MIME的类型。如把其类型设定为JSON;

  reply_to : 用于命名一个回调Queue;

  correlation_id : 用于与相关联的请求的RPC响应.

  现在我们就开始RPC的程序吧!

client的代码如下:

Java代码   收藏代码
  1. package com.abin.rabbitmq;  
  2.   
  3. import java.util.UUID;  
  4.   
  5. import com.rabbitmq.client.AMQP.BasicProperties;  
  6. import com.rabbitmq.client.Channel;  
  7. import com.rabbitmq.client.Connection;  
  8. import com.rabbitmq.client.ConnectionFactory;  
  9. import com.rabbitmq.client.QueueingConsumer;  
  10.   
  11. public class RPCClient {  
  12.     private Connection connection;  
  13.     private Channel channel;  
  14.     private String requestQueueName = "rpc_queue";  
  15.     private String replyQueueName;  
  16.     private QueueingConsumer consumer;  
  17.   
  18.     public RPCClient() throws Exception {  
  19.         ConnectionFactory factory = new ConnectionFactory();  
  20.         factory.setHost("localhost");  
  21.         connection = factory.newConnection();  
  22.         channel = connection.createChannel();  
  23.   
  24.         replyQueueName = channel.queueDeclare().getQueue();  
  25.         consumer = new QueueingConsumer(channel);  
  26.         channel.basicConsume(replyQueueName, true, consumer);  
  27.     }  
  28.   
  29.     public String call(String message) throws Exception {  
  30.         String response = null;  
  31.         String corrId = UUID.randomUUID().toString();  
  32.   
  33.         BasicProperties props = new BasicProperties();  
  34.         props.setReplyTo(replyQueueName);  
  35.         props.setCorrelationId(corrId);  
  36.   
  37.         channel.basicPublish("", requestQueueName, props, message.getBytes());  
  38.   
  39.         while (true) {  
  40.             QueueingConsumer.Delivery delivery = consumer.nextDelivery();  
  41.             if (delivery.getProperties().getCorrelationId().equals(corrId)) {  
  42.                 response = new String(delivery.getBody(), "UTF-8");  
  43.                 break;  
  44.             }  
  45.         }  
  46.   
  47.         return response;  
  48.     }  
  49.   
  50.     public void close() throws Exception {  
  51.         connection.close();  
  52.     }  
  53.   
  54.     public static void main(String[] argv) {  
  55.         RPCClient fibonacciRpc = null;  
  56.         String response = null;  
  57.         try {  
  58.             fibonacciRpc = new RPCClient();  
  59.   
  60.             System.out.println(" [x] Requesting fib(30)");  
  61.             response = fibonacciRpc.call("30");  
  62.             System.out.println(" [.] Got '" + response + "'");  
  63.             System.out.println(" [x] Requesting fib(-1)");  
  64.             response = fibonacciRpc.call("-1");  
  65.             System.out.println(" [.] Got '" + response + "'");  
  66.             System.out.println(" [x] Requesting fib(a)");  
  67.             response = fibonacciRpc.call("a");  
  68.             System.out.println(" [.] Got '" + response + "'");  
  69.         } catch (Exception e) {  
  70.             e.printStackTrace();  
  71.         } finally {  
  72.             if (fibonacciRpc != null) {  
  73.                 try {  
  74.                     fibonacciRpc.close();  
  75.                 } catch (Exception ignore) {  
  76.                 }  
  77.             }  
  78.         }  
  79.     }  
  80. }  

 

 server的代码如下:

Java代码   收藏代码
  1. package com.abin.rabbitmq;  
  2.   
  3. import com.rabbitmq.client.AMQP.BasicProperties;  
  4. import com.rabbitmq.client.Channel;  
  5. import com.rabbitmq.client.Connection;  
  6. import com.rabbitmq.client.ConnectionFactory;  
  7. import com.rabbitmq.client.QueueingConsumer;  
  8.   
  9. public class RPCServer {  
  10.     private static final String RPC_QUEUE_NAME = "rpc_queue";  
  11.   
  12.     private static int fib(int n) {  
  13.         if (n > 1)  
  14.             return fib(n - 1) + fib(n - 2);  
  15.         else  
  16.             return n;  
  17.     }  
  18.   
  19.     public static void main(String[] argv) {  
  20.         Connection connection = null;  
  21.         Channel channel = null;  
  22.         try {  
  23.             ConnectionFactory factory = new ConnectionFactory();  
  24.             factory.setHost("localhost");  
  25.   
  26.             connection = factory.newConnection();  
  27.             channel = connection.createChannel();  
  28.   
  29.             channel.queueDeclare(RPC_QUEUE_NAME, falsefalsefalsenull);  
  30.   
  31.             channel.basicQos(1);  
  32.   
  33.             QueueingConsumer consumer = new QueueingConsumer(channel);  
  34.             channel.basicConsume(RPC_QUEUE_NAME, false, consumer);  
  35.   
  36.             System.out.println(" [x] Awaiting RPC requests");  
  37.   
  38.             while (true) {  
  39.                 String response = null;  
  40.   
  41.                 QueueingConsumer.Delivery delivery = consumer.nextDelivery();  
  42.   
  43.                 BasicProperties props = delivery.getProperties();  
  44.                 BasicProperties replyProps = new BasicProperties();  
  45.                 replyProps.setCorrelationId(props.getCorrelationId());  
  46.   
  47.                 try {  
  48.                     String message = new String(delivery.getBody(), "UTF-8");  
  49.                     int n = Integer.parseInt(message);  
  50.   
  51.                     System.out.println(" [.] fib(" + message + ")");  
  52.                     response = "" + fib(n);  
  53.                 } catch (Exception e) {  
  54.                     System.out.println(" [.] " + e.toString());  
  55.                     response = "";  
  56.                 } finally {  
  57.                     channel.basicPublish("", props.getReplyTo(), replyProps,  
  58.                             response.getBytes("UTF-8"));  
  59.   
  60.                     channel.basicAck(delivery.getEnvelope().getDeliveryTag(),  
  61.                             false);  
  62.                 }  
  63.             }  
  64.         } catch (Exception e) {  
  65.             e.printStackTrace();  
  66.         } finally {  
  67.             if (connection != null) {  
  68.                 try {  
  69.                     connection.close();  
  70.                 } catch (Exception ignore) {  
  71.                 }  
  72.             }  
  73.         }  
  74.     }  
  75. }  

 

先运行服务器端,运行结果如下:

Java代码   收藏代码
  1. [x] Awaiting RPC requests  

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

Java代码   收藏代码
  1. [x] Requesting fib(30)  
  2. [.] Got '832040'  
  3. [x] Requesting fib(-1)  
  4. [.] Got '-1'  
  5. [x] Requesting fib(a)  
  6. [.] Got ''  

   在服务器还可以出现:

Java代码   收藏代码
  1. [.] fib(30)  
  2. [.] fib(-1)  
  3. [.] java.lang.NumberFormatException: For input string: "a"  
资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在当今的软件开发领域,自动化构建与发布是提升开发效率和项目质量的关键环节。Jenkins Pipeline作为一种强大的自动化工具,能够有效助力Java项目的快速构建、测试及部署。本文将详细介绍如何利用Jenkins Pipeline实现Java项目的自动化构建与发布。 Jenkins Pipeline简介 Jenkins Pipeline是运行在Jenkins上的一套工作流框架,它将原本分散在单个或多个节点上独立运行的任务串联起来,实现复杂流程的编排与可视化。它是Jenkins 2.X的核心特性之一,推动了Jenkins从持续集成(CI)向持续交付(CD)及DevOps的转变。 创建Pipeline项目 要使用Jenkins Pipeline自动化构建发布Java项目,首先需要创建Pipeline项目。具体步骤如下: 登录Jenkins,点击“新建项”,选择“Pipeline”。 输入项目名称和描述,点击“确定”。 在Pipeline脚本中定义项目字典、发版脚本和预发布脚本。 编写Pipeline脚本 Pipeline脚本是Jenkins Pipeline的核心,用于定义自动化构建和发布的流程。以下是一个简单的Pipeline脚本示例: 在上述脚本中,定义了四个阶段:Checkout、Build、Push package和Deploy/Rollback。每个阶段都可以根据实际需求进行配置和调整。 通过Jenkins Pipeline自动化构建发布Java项目,可以显著提升开发效率和项目质量。借助Pipeline,我们能够轻松实现自动化构建、测试和部署,从而提高项目的整体质量和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值