RPC原理及其调用过程
远程过程调用,简称为RPC,是一个计算机通信协议,它允许运行于一台计算机的程序调用另一台计算机的子程序,而无需额外地为这个交互作用编程。
RPC与传统的HTTP对比
优点:
1. 传输效率高(二进制传输)
2. 发起调用的一方无需知道RPC的具体实现,如同调用本地函数般调用
缺点:
1. 通用性不如HTTP好(HTTP是标准协议)
总结:RPC适合内部服务间的通信调用;HTTP适合面向用户与服务间的通信调用
RPC调用过程如下:

1. 调用者(客户端Client)以本地调用的方式发起调用;
2. Client stub(客户端存根)收到调用后,负责将被调用的方法名、参数等打包编码成特定格式的能进行网络传输的消息体;
3. Client stub将消息体通过网络发送给服务端;
4. Server stub(服务端存根)收到通过网络接收到消息后按照相应格式进行拆包解码,获取方法名和参数;
5. Server stub根据方法名和参数进行本地调用;
6. 被调用者(Server)本地调用执行后将结果返回给server stub;
7. Server stub将返回值打包编码成消息,并通过网络发送给客户端;
8. Client stub收到消息后,进行拆包解码,返回给Client;
9. Client得到本次RPC调用的最终结果。
对于RPC调用流程的实现,抛开调用方与被调用方,其核心主要是:消息协议和传输控制的实现
(1). RPC消息协议:客户端调用的参数和服务端的返回值这些在网络上传输的数据以何种方式打包编码和拆包解码
RPC的消息协议在设计时主要要考虑,消息转换及传输的效率,为解决消息转换及传输的效率,可以以二进制的方式传输消息,使用原始的二进制传输可以省去中间转换的环节并减少传输的数据量。
在Python中可以使用struct模块对二进制进行编码和解码:
struct.pact将其它类型转换为二进制,通常用于消息长度的转换:
import struct # 将整数2转换成适用网络传输的无符号的4个字节整数
>>> struct.pack('!I', 2)
'\x00\x00\x00\x02'
struct.unpack将二进制类型转换为其它类型:
byte_data = '\x00\x00\x00\x02'
# 将2对应的二进制 转换为十进制整数 返回结果是个元组
>>> struct.unpack('!I',byte_data)
(2,)
(2). RPC传输控制
对于消息数据的传输,主要有HTTP传输和TCP传输,鉴于TCP传输的可靠性,RPC的传输一般使用TCP作为传输协议
在TCP传输中客户端与服务端通过socket进行通信,通信流程:

RPC使用TCP进行传输控制的实现
import socket class Channel(object):
"""
与客户端建立网络连接
""" def __init__(self, host, port):
self.host = host # 服务器地址
self.port = port # 服务器端口 def get_connection(self):
"""
获取一个tcp连接
"""
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((self.host, self.port))
return sock class Server(object):
def __init__(self, host, port, handlers):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.host = host
self.port = port
self.sock.bind((host, port))
self.handlers = handlers def serve(self):
"""
开启服务器运行,提供RPC服务
"""
# 开启服务监听,等待客户端连接
self.sock.listen(128)
print("开始监听")
while True:
# 接收客户端的连接请求
conn, addr = self.sock.accept()
print("建立连接{}".format(str(addr))) # 创建ServerStub对象,完成客户端具体的RPC调用
stub = ServerStub(conn, self.handlers)
try:
while True:
stub.process()
except EOFError:
# 表示客户端关闭了连接
print("客户端关闭连接")
# 关闭服务端连接
conn.close()
通过Socket使得RPC客户端与服务器进行通信
TCP服务端
sock = socket.socket() # 创建一个套接字
sock.bind() # 绑定端口
sock.listen() # 监听连接
sock.accept() # 接受新连接
sock.close() # 关闭服务器套接字 TCP客户端
sock = socket.socket() # 创建一个套接字
sock.connect() # 连接远程服务器
sock.recv() # 读
sock.send() # 写
sock.sendall() # 完全写
sock.close() # 关闭
RPC服务的实现:为了能让RPC服务器同时处理多个客户端的请求,提升性能,可以采用多线程、多进程方式实现,下面分别介绍这两种方式实现的RPC服务
多线程RPC服务:
class ThreadServer(object):
"""
多线程RPC服务器
""" def __init__(self, host, port, handlers):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.host = host
self.port = port
self.sock.bind((host, port))
self.handlers = handlers def serve(self):
"""
开始服务
"""
self.sock.listen(128)
print("开始监听")
while True:
conn, addr = self.sock.accept()
print("建立链接{}".format(str(addr)))
t = threading.Thread(target=self.handle, args=(conn,))
t.start() def handle(self, client):
stub = ServerStub(client, self.handlers)
try:
while True:
stub.process()
except EOFError:
print("客户端关闭连接") client.close()
多进程RPC服务:
class MultiProcessServer(object):
"""
多进程服务器
""" def __init__(self, host, port, handlers):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.host = host
self.port = port
self.sock.bind((host, port))
self.handlers = handlers def serve(self):
"""
开始服务
"""
self.sock.listen(128)
print("开始监听")
while True:
conn, addr = self.sock.accept()
print("建立链接{}".format(str(addr)))
t = Process(target=self.handle, args=(conn,))
t.start() def handle(self, client):
stub = ServerStub(client, self.handlers)
try:
while True:
stub.process()
except EOFError:
print("客户端关闭连接") client.close()
RPC原理及其调用过程的更多相关文章
- RPC框架调用过程详解
RPC框架调用过程详解 2017年09月16日 21:14:08 荷叶清泉 阅读数 6275 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. ...
- rpc调用过程
在openstack中,各个组件之间的调用遵循RESTful风格,而组件内部各服务之间的相互调用采用rpc远程调用,比如nova-conductor和nova-compute rpc原理: 首先了解什 ...
- go微服务框架go-micro深度学习(四) rpc方法调用过程详解
上一篇帖子go微服务框架go-micro深度学习(三) Registry服务的注册和发现详细解释了go-micro是如何做服务注册和发现在,服务端注册server信息,client获取server的地 ...
- go微服务框架go-micro深度学习 rpc方法调用过程详解
摘要: 上一篇帖子go微服务框架go-micro深度学习(三) Registry服务的注册和发现详细解释了go-micro是如何做服务注册和发现在,服务端注册server信息,client获取serv ...
- java多态的实现原理(JVM调用过程)(综合多篇文章,参考见文末)
一个对象变量可以指示多种实际类型的现象称为多态 允许不同类的对象对同一消息做出响应.方法的重载.类的覆盖正体现了多态. 1.多态的机制 1.1 本质上多态分两种 1.编译时多态(又称静态多态) 2.运 ...
- Openstack Nova 源码分析 — RPC 远程调用过程
目录 目录 Nova Project Services Project 的程序入口 setuppy Nova中RPC远程过程调用 nova-compute RPC API的实现 novacompute ...
- Hbase的WAL在RegionServer基本调用过程
版权声明:本文由熊训德原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/221 来源:腾云阁 https://www.qclo ...
- 你应该知道的RPC原理
你应该知道的RPC原理 在学校期间大家都写过不少程序,比如写个hello world服务类,然后本地调用下,如下所示.这些程序的特点是服务消费方和服务提供方是本地调用关系. 而一旦踏入公司尤其是大型互 ...
- RPC原理解析
1.RPC原理解析 1.1 什么是RPC RPC(Remote Procedure Call Protocol) --远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络 ...
随机推荐
- (String) leetcode 67. Add Binary
Given two binary strings, return their sum (also a binary string). The input strings are both non-em ...
- consul实现分布式锁
分布式一致性问题: 分布式的CAP理论告诉我们"任何一个分布式系统都无法同时满足一致性(Consistency).可用性(Availability)和分区容错性(Partition tole ...
- react项目后台及上线步骤
应同学要求,本人将react项目创建后台及上线流程书写如下: 前端部分 略…… 后台部分 (注:这里的后台是用的nodejs搭建的,使用的是express框架+ejs模板) 首先通过express快速 ...
- day20面向对象三大特性 , 类嵌套
#!/usr/bin/env python# -*- coding:utf-8 -*- # 1.简述面向对象三大特性并用代码表示."""封装:class Account: ...
- Redis实战阅读笔记——第二章(redis重构web)
在性能的要求下,如何用redis重构已有的已有的部分,其实整个例子背后的思路挺好的.在应用缓存的过程中,还有一指标个需要考虑,读写比.
- 有关mysql索引
1.首先我们需要明确一下什么是索引以及为什么要使用索引: 索引在MySQL中也叫做“键”,是存储引擎用于快速找到记录的一种数据结构.在生产环境中,对于数据库我们最常进行的是查询的操作,而当我们的数据非 ...
- docker安装redis
查询镜像 docker search redis 拉取镜像 docker pull redis 启动容器 docker run --name redis -p 6379:6379 -d --resta ...
- 7、字典和string的用法
#dic={1:'alex','age':35,'hobby':{'girl_name':'铁锤','age':45},'is_handsome':True} # dic={'age':'alex', ...
- Spring框架-IOC/DI详细学习
一.IOC/DI概念 参考博客:https://www.cnblogs.com/xdp-gacl/p/4249939.html IOC(inversion of control, 控制反转)是一种设计 ...
- Appnium-API-Execute Mobile Command
Execute Mobile Command Java:driver.executeScript("mobile: scroll", ImmutableMap.of("d ...