一. 简介

将一个函数运行在远程计算机上并且等待获取那里的结果,这个称作远程过程调用(Remote Procedure Call)或者 RPC。

RPC是一个计算机通信协议。

1. 类比:

将计算机服务运行理解为厨师做饭,厨师想做一个小葱拌豆腐,厨师需要洗小葱、切豆腐、调汁、凉拌。他一个人完成所有的事,如同古老的集中式应用,一台计算机做所有的事。

制作小葱拌豆腐{
厨师>洗小葱>切豆腐>凉拌
}
rpc应用场景 而如今,饭店做大了,有钱了,专职分工来干活,不再是厨师单打独斗,备菜师傅准备小葱、豆腐,切菜师傅切小葱、豆腐,厨师只负责调味,完成食品。

制作小葱拌豆腐{
备菜师>洗菜
切菜师>切菜
厨师>调味
}
此时一件事好多人在做,厨师就得和其他人沟通,通知备菜、洗菜师傅的这个动作就是远程过程调用(RPC)。 这个过程在计算机系统中,一个电商的下单过程,涉及物流、支付、库存、红包等多个系统,多个系统又在多个服务器上,由不同的技术团队负责,整个下单过程,需要所有团队进行远程调用。 下单{
库存>减少库存
支付>扣款
红包>减免红包
物流>生成订单
}

二. 到底什么是rpc

rpc指的是在计算机A上的进程,调用另外一台计算机B的进程,A上的进程被挂起,B上的被调用进程开始执行后,产生返回值给A,A继续执行。

调用方可以通过参数将信息传递给被调用方,而后通过返回结果得到信息,这个过程对于开发人员来说是透明的如同厨师一样,服务员把菜单给后厨,厨师告诉洗菜人,备菜人,开始工作,完成工作后,整个过程对于服务员是透明的,他完全不用管后厨是怎么把菜做好的。

由于服务在不同的机器上,远程调用必经网络通信,调用服务必须写一坨网络通信代码,很容易出错且很复杂,因此就出现了RPC框架。

阿里巴巴的   Dubbo       java
新浪的   Motan java
谷歌的  gRPC 多语言
Apache thrift 多语言
rpc封装了数据的序列化,反序列化,以及传输协议

1. python实现RPC

利用RabbitMQ构建一个RPC系统,包含了客户端和RPC服务器,依旧使用pika模块

2. Callback queue 回调队列

一个客户端向服务器发送请求,服务器端处理请求后,将其处理结果保存在一个存储体中。而客户端为了获得处理结果,那么客户在向服务器发送请求时,同时发送一个回调队列地址reply_to。

3. Correlation id 关联标识

一个客户端可能会发送多个请求给服务器,当服务器处理完后,客户端无法辨别在回调队列中的响应具体和那个请求时对应的。为了处理这种情况,客户端在发送每个请求时,同时会附带一个独有correlation_id属性,这样客户端在回调队列中根据correlation_id字段的值就可以分辨此响应属于哪个请求。

客户端发送请求:某个应用将请求信息交给客户端,然后客户端发送RPC请求,在发送RPC请求到RPC请求队列时,客户端至少发送带有reply_to以及correlation_id两个属性的信息

服务器端工作流: 等待接受客户端发来RPC请求,当请求出现的时候,服务器从RPC请求队列中取出请求,然后处理后,将响应发送到reply_to指定的回调队列中

客户端接受处理结果: 客户端等待回调队列中出现响应,当响应出现时,它会根据响应中correlation_id字段的值,将其返回给对应的应用

(1). 过程

1.启动rpc客户端,等待接收数据到来,来了之后就进行处理,再将结果丢进队列
2.启动rpc服务端,发起请求

(2). rpc_server.py

import pika
import uuid
class FibonacciRpcClient(object):
def __init__(self):
# 客户端启动时,创建回调队列,会开启会话用于发送RPC请求以及接受响应
# 建立连接,指定服务器的ip地址
self.connection = pika.BlockingConnection(pika.ConnectionParameters(
host='192.168.119.10'))
# 建立一个会话,每个channel代表一个会话任务
self.channel = self.connection.channel() # 声明回调队列,再次声明的原因是,服务器和客户端可能先后开启,该声明是幂等的,多次声明,但只生效一次
#exclusive=True 参数是指只对首次声明它的连接可见
#exclusive=True 会在连接断开的时候,自动删除
result = self.channel.queue_declare(exclusive=True)
# 将次队列指定为当前客户端的回调队列
self.callback_queue = result.method.queue
# 客户端订阅回调队列,当回调队列中有响应时,调用`on_response`方法对响应进行处理;
self.channel.basic_consume(self.on_response, no_ack=True,
queue=self.callback_queue) # 对回调队列中的响应进行处理的函数
def on_response(self, ch, method, props, body):
if self.corr_id == props.correlation_id:
self.response = body # 发出RPC请求
# 例如这里服务端就是一个切菜师傅,菜切好了,需要传递给洗菜师傅,这个过程是发送rpc请求
def call(self, n):
# 初始化 response
self.response = None
# 生成correlation_id 关联标识,通过python的uuid库,生成全局唯一标识ID,保证时间空间唯一性
self.corr_id = str(uuid.uuid4())
# 发送RPC请求内容到RPC请求队列`s14rpc`,同时发送的还有`reply_to`和`correlation_id`
self.channel.basic_publish(exchange='',
routing_key='s14rpc',
properties=pika.BasicProperties(
reply_to=self.callback_queue,
correlation_id=self.corr_id,
),
body=str(n))
while self.response is None:
self.connection.process_data_events()
return int(self.response) # 建立客户端
fibonacci_rpc = FibonacciRpcClient() # 发送RPC请求,丢进rpc队列,等待客户端处理完毕,给与响应
print("发送了请求sum(99)")
response = fibonacci_rpc.call(99) print("得到远程结果响应%r" % response)

(3). rpc_client.py

import pika
# 建立连接,服务器地址为localhost,可指定ip地址
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='192.168.119.10'))
# 建立会话
channel = connection.channel()
# 声明RPC请求队列
channel.queue_declare(queue='s14rpc') # 模拟一个进程,例如切菜师傅,等着洗菜师傅传递数据
def sum(n):
n+=100
return n
# 对RPC请求队列中的请求进行处理 def on_request(ch, method, props, body):
print(body,type(body))
n = int(body)
print(" 正在处理sum(%s)" % n)
# 调用数据处理方法
response = sum(n)
# 将处理结果(响应)发送到回调队列
ch.basic_publish(exchange='',
# reply_to代表回复目标
routing_key=props.reply_to,
# correlation_id(关联标识):用来将RPC的响应和请求关联起来。
properties=pika.BasicProperties(correlation_id= \
props.correlation_id),
body=str(response))
ch.basic_ack(delivery_tag=method.delivery_tag) # 负载均衡,同一时刻发送给该服务器的请求不超过一个
channel.basic_qos(prefetch_count=1)
channel.basic_consume(on_request, queue='s14rpc')
print("等待接收rpc请求") #开始消费
channel.start_consuming()

RPC之远程过程调用的更多相关文章

  1. RabbitMQ入门教程(八):远程过程调用RPC

    原文:RabbitMQ入门教程(八):远程过程调用RPC 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.cs ...

  2. Thrift架构~从图中理解thrift,它事实上是一种远程过程调用

    thrift为我们简化了tcp通讯,它可以使用我们方便的建立各种语言的服务端与客户端,并实现客户端对服务器的远程过程调用,简单的说就是服务器通过thrift架构对外开放一些接口,并自己实现这些接口,如 ...

  3. RabbitMQ九:远程过程调用RPC

    定义 RPC(Remote Procedure Call Protocol)——远程过程调用协议:它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.RPC协议假定某些传输协议 ...

  4. 【RPC】远程接口调用实例 的几种方式比较

    pring中,用JMS搞RPC时会用到: org.springframework.jms.remoting.JmsInvokerServiceExporter org.springframework. ...

  5. RPC远程过程调用

    什么是RPC: 将一个函数运行在远程计算机上并且等待获取那里的结果,这个称作RPC: (Remote Procedure Call远程过程调用) RPC是一个计算机通信协议. rpc指的是在计算机A上 ...

  6. rabbitMQ学习笔记(七) RPC 远程过程调用

    关于RPC的介绍请参考百度百科里的关于RPC的介绍:http://baike.baidu.com/view/32726.htm#sub32726 现在来看看Rabbitmq中RPC吧!RPC的工作示意 ...

  7. RabbitMQ学习系列(五): RPC 远程过程调用

    前面讲过一些RabbitMQ的安装和用法,也说了说RabbitMQ在一般的业务场景下如何使用.不知道的可以看我前面的博客,http://www.cnblogs.com/zhangweizhong/ca ...

  8. RabbitMQ 实现远程过程调用RPC

    RPC调用的顺序1. 在客户端初始化的时候,也就是SimpleRpcClient类初始化的时候,它会随机的创建一个callback队列,用于存放服务的返回值,这个队列是exclusive的.连接断开就 ...

  9. python中RabbitMQ的使用(远程过程调用RPC)

    在RabbitMQ消息队列中,往往接收者.发送者不止是一个身份.例如接接收者收到消息并且需要返回给发送者. 此时接收者.发送者的身份不再固定! 我们来模拟该情形: 假设有客户端client,服务端se ...

随机推荐

  1. HDU3567 Eight II —— IDA*算法

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3567 Eight II Time Limit: 4000/2000 MS (Java/Others)  ...

  2. vue2实现自定义样式radio单选框

    先上效果 <div class="reply"> 主编已回复: <div class="radio-box" v-for="(ite ...

  3. MYSQL学习拓展一:MySQL 存储过程之游标的使用!

    一.MySQL游标的概念 游标介绍: MySQL的游标(cursor)是一个重要的概念,通过查找资料与自己的理解,主要得出以下几点关于自己的理解. 有数据缓冲的思想:游标的设计是一种数据缓冲区的思想, ...

  4. JRE System Library 与Java EE Libraries的区别

    JRE System Library是只要做java开发都需要的完整的.标准的库.  Java EE5 Libraries只是java三个方向中做java EE所需要的库.如果做Web方面的开发的话就 ...

  5. 使用SVPullToRefresh实现下拉刷新和下拉加载

    移动端开发中,“下拉刷新”和“上拉加载更多”早已在各大App中随处可见.也非常容易就能找到直接可供使用的第三方资源.譬如EGOTableViewPullRefresh(下拉刷新)和LoadMoreTa ...

  6. 喵哈哈村的魔法考试 Round #1 (Div.2)

    比赛地址:http://qscoj.cn/contest/2/ 都是中文题,这里不在详述题意 A.喵哈哈村的魔法石 分析:暴力求解 #include<iostream> #include& ...

  7. ASP.NET Core MVC 2.x 全面教程_ASP.NET Core MVC 21. Model 验证 Again

    深入的将Model验证 手动添加验证的错误 view里面显示每个属性的验证错误信息 显示整个model级别错误 自定义验证 如果业务逻辑需要比较复杂的验证.而且这个验证逻辑可能到处复用的话就应该考虑使 ...

  8. Android 截屏的各种骚操作

    本文公众号「AndroidTraveler」首发. 背景 在实际的应用场景中,Android 手机的截屏其实是很普遍的. 比如说 PPT 演示,比如说技术博客图文并茂讲解. 因此懂得 Android ...

  9. 51nod 1003【数学】

    思路: 2和5能构成0,然后就是看2和5因子组成个数,然而我们知道,1-n中2的因子数肯定>5的,所以我们只要求一下1-n中5的因子个数就好了... #include <stdio.h&g ...

  10. sql server编写通用脚本自动统计各表数据量心得

    工作过程中,如果一个数据库的表比较多,手工编写统计脚本就会比较繁琐,于是摸索出自动生成各表统计数据量脚本的通用方法,直接上代码: /* 脚本来源:https://www.cnblogs.com/zha ...