远程过程调用,简称为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原理及其调用过程的更多相关文章

  1. RPC框架调用过程详解

    RPC框架调用过程详解 2017年09月16日 21:14:08 荷叶清泉 阅读数 6275   版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. ...

  2. rpc调用过程

    在openstack中,各个组件之间的调用遵循RESTful风格,而组件内部各服务之间的相互调用采用rpc远程调用,比如nova-conductor和nova-compute rpc原理: 首先了解什 ...

  3. go微服务框架go-micro深度学习(四) rpc方法调用过程详解

    上一篇帖子go微服务框架go-micro深度学习(三) Registry服务的注册和发现详细解释了go-micro是如何做服务注册和发现在,服务端注册server信息,client获取server的地 ...

  4. go微服务框架go-micro深度学习 rpc方法调用过程详解

    摘要: 上一篇帖子go微服务框架go-micro深度学习(三) Registry服务的注册和发现详细解释了go-micro是如何做服务注册和发现在,服务端注册server信息,client获取serv ...

  5. java多态的实现原理(JVM调用过程)(综合多篇文章,参考见文末)

    一个对象变量可以指示多种实际类型的现象称为多态 允许不同类的对象对同一消息做出响应.方法的重载.类的覆盖正体现了多态. 1.多态的机制 1.1 本质上多态分两种 1.编译时多态(又称静态多态) 2.运 ...

  6. Openstack Nova 源码分析 — RPC 远程调用过程

    目录 目录 Nova Project Services Project 的程序入口 setuppy Nova中RPC远程过程调用 nova-compute RPC API的实现 novacompute ...

  7. Hbase的WAL在RegionServer基本调用过程

    版权声明:本文由熊训德原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/221 来源:腾云阁 https://www.qclo ...

  8. 你应该知道的RPC原理

    你应该知道的RPC原理 在学校期间大家都写过不少程序,比如写个hello world服务类,然后本地调用下,如下所示.这些程序的特点是服务消费方和服务提供方是本地调用关系. 而一旦踏入公司尤其是大型互 ...

  9. RPC原理解析

    1.RPC原理解析 1.1 什么是RPC RPC(Remote Procedure Call Protocol) --远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络 ...

随机推荐

  1. Alertmanager 集群

    Alertmanager 集群搭建 环境准备:2台主机 (centos 7) 192.168.31.151 192.168.31.144 1.安装部署 192.168.31.151 cd /usr/l ...

  2. windows一键部署java项目

    windows一键部署java项目 因为公司需求,要在windows的环境上做一键部署启动java项目,同时还要支持从安装界面动态修改配置文件的IP地址.就像安装软件一样将jdk,tomcat,mys ...

  3. 多输入select

    目录 多输入select IO模型 select介绍 小demo 注意 引入电子书 title: 多输入select date: 2019/3/20 17:21:34 toc: true --- 多输 ...

  4. 编写高质量的Python代码系列(八)之部署

    Python提供了一些工具,使我们可以把软件部署到不同的环境中.它也提供了一些模块,令开发者可以把程序编写的更加健壮.本章讲解如何使用Python调试.优化并测试程序,以提升其质量与性能. 第五十四条 ...

  5. 使用numpy的小惊喜

    今天使用 numpy.true_divide 发现个有趣的事情, 下面的代码18.19行如果去掉,就会报下面的  RuntimeWarning def multivalue_divide(timese ...

  6. Windows API 调用示例

    Ø  简介 本文主要记录 Windows API 的调用示例,因为这项技术并不常用,属于 C# 中比较孤僻或接触底层的技术,并不常用.但是有时候也可以借助他完成一些 C# 本身不能完成的功能,例如:通 ...

  7. java(12)字符串

    一.字符串概述 1.1如何使用字符串 1)定义并初始化字符串 2)使用字符串,对字符串进行一些处理 1.2字符串的长度 语法: 字符串1.length();  -->返回字符串1的长度 publ ...

  8. 自适应rem.js

    用rem.js来实现自适应屏幕大小,要注意border不用rem做单位  代码如下: (function (doc, win) { //orientationchange : 判断手机是水平方向还是垂 ...

  9. Python 高级特性之:生成器(generator)和迭代器(Iterator)

    前言: 之前学习Python自动化,接触了不少python的学习,对生成器印象尤其深,网上也看了很多介绍,下面主要是这些概念的个人学习整理(如侵删). 正文: 如要创建一个非常大的列表,受到内存限制, ...

  10. JavaFX - 富互联网应用

    JavaFX教程™ --必看https://www.yiibai.com/javafx /================= 富互联网应用 是那些提供与Web应用程序类似的功能,并可作为桌面应用程序体 ...