一、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

rabbitmq学习(四):利用rabbitmq实现远程rpc调用的更多相关文章

  1. 【c#】RabbitMQ学习文档(六)RPC(远程调用)

    远程过程调用(Remote Proceddure call[RPC]) (本实例都是使用的Net的客户端,使用C#编写) 在第二个教程中,我们学习了如何使用工作队列在多个工作实例之间分配耗时的任务. ...

  2. 【RabbitMQ学习之一】RabbitMQ入门

    环境 win7 rabbitmq-server-3.7.17 Erlang 22.1 RabbitMQ使用Erlang语言开发消息中间件.RabbitMQ基于AMQP(高级消息队列协议)协议,更适合业 ...

  3. rabbitMQ学习2-Python与rabbitmq

    python客户端 # rabbitmq官方推荐的python客户端pika模块 pip3 install pika 应用场景1:单发送单接收 1.生产-消费者模型 P 是生产者 C 是消费者 中间h ...

  4. rabbitmq学习-如何安装rabbitmq

    学习当然还是需要看官网地址的哈 官网地址 你可能会说老铁,看不懂英文咋办?我只能说各大翻译软件以及广大网友总有一款是你喜欢的 广大网友翻译的 中文文档 什么是rabbitmq? rabbitmq (R ...

  5. [RabbitMQ学习笔记] - 初识RabbitMQ

    RabbitMQ是一个由erlang开发的AMQP的开源实现. 核心概念 Message 消息,消息是不具名的,它由消息头和消息体组成,消息体是不透明的,而消息头则由 一系列的可选属性组成,这些属性包 ...

  6. rabbitmq学习(二):rabbitmq(消息队列)的作用以及rabbitmq之直连交换机

    前言 上篇介绍了AMQP的基本概念,组成及其与rabbitmq的关系.了解了这些东西后,下面我们开始学习rabbitmq(消息队列)的作用以及用java代码和rabbitmq通讯进行消息发布和接收.因 ...

  7. RabbitMQ学习之旅(一)

    RabbitMQ学习总结(一) RabbitMQ简介 RabbitMQ是一个消息代理,其接收并转发消息.类似于现实生活中的邮局:你把信件投入邮箱的过程,相当于往队列中添加信息,因为所有邮箱中的信件最终 ...

  8. 自研发RPC调用框架

    自主研发设计RPC远程调用框架,实现服务自动注册,服务发现,远程RPC调用,后续实现服务负载均衡 主要包括:客户端服务,服务端,服务发现,服务注册 github地址:https://github.co ...

  9. RabbitMQ学习之基于spring-rabbitmq的RPC远程调用

    http://blog.csdn.net/zhu_tianwei/article/details/40920985 spring-rabbitmq中实现远程接口调用,主要在com.rabbitmq.s ...

随机推荐

  1. TFS2015源代码管理器无法建立团队项目的问题

    最近在服务器安装了微软最新版的TFS2015  正版要钱,网络上还没有能找到可用的key,因此我只能使用试用版. 安装完成后,使用我本地的vs2013  vs2012  vs2010  vs2014 ...

  2. tcp socket http(复制的)

    物理层-- 数据链路层-- 网络层--                       IP协议 传输层--                       TCP协议 会话层-- 表示层和应用层--     ...

  3. 系统管理命令之tty

    在Linux操作系统中,所有外围设备都有其名称与代号,这些名称代号以特殊文件的类型存放于/dev目录下.你可以执行tty指令查询目前使用的终端机的文件名称. 1.命令帮助: # tty -- help ...

  4. CSS实现超出DIV宽度文字自动隐藏并显示省略号

    当文字超出DIV宽度时,超出的文字部分省略,并用显示省略号代替,css代码如下: div.ellipsis { padding-left: 5px; text-align: left; text-ov ...

  5. Fms3和Flex打造在线多人视频会议和视频聊天(附原代码)

    Flex,Fms3系列文章导航 Flex,Fms3相关文章索引 本篇是视频聊天,会议开发实例系列文章的第3篇,该系列所有文章链接如下: http://www.cnblogs.com/aierong/a ...

  6. Vue学习笔记之Vue指令系统介绍

    所谓指令系统,大家可以联想咱们的cmd命令行工具,只要我输入一条正确的指令,系统就开始干活了. 在vue中,指令系统,设置一些命令之后,来操作我们的数据属性,并展示到我们的DOM上. OK,接下来我们 ...

  7. LINUX实践--程序破解

    实验思想 本次实验的主要思想有两个,第一个是修改跳转指令,把它变成无条件跳转使得无论输入什么用户名都跳转到失败的那个选项中去,第二个思想是修改比对的内容,即不判断条件,从而成功 实验步骤 1.首先从老 ...

  8. Java面试知识点总结及解析

    声明:有人说, 有些面试题很变态,个人认为其实是因为我们基础不扎实或者没有深入.本篇文章来自一位很资深的前辈对于最近java面试题目所做的总结归纳,有170道题目 ,知识面很广 ,而且这位前辈对于每个 ...

  9. sed删除包含指定字符串的所有行

    1.以删除文件example.txt中包含字符串"=yes"的行为例,example.txt文件有以下内容: dadasdfsadf=yes=sds dsdadasdkfk dsd ...

  10. CF_884_F(NetFlow)

    codeforces_884_f 题目大意:给出一串长为n的字符串(保证n为偶数),定义反回文串为每一个位置的对应位置上的字母都不等于它(for each i : s[i] != s[n+1-i]), ...