远程过程调用(英语:Remote Procedure Call,缩写为 RPC,也叫远程程序调用)是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程。如果涉及的软件采用面向对象编程,那么远程过程调用亦可称作远程调用或远程方法调用
在单台计算机中,我们可以通过程序调用来传递控制和数据;或者说通过程序调用,我们可以将多个程序组成一个整体来实现某个功能。
如果将这种调用机制推广到多台彼此间可以进行网络通讯的计算机,由多台计算机中的多个程序组成一个整体来实现某个功能,这也是可以的。调用的一方(发起远程过程调用,然后调用这方的环境挂起,参数通过网络传递给被调用方,被调用的一方执行程序,当程序执行完成后,产生的结果再通过网络回传给调用的一方,调用的一方恢复继续执行。这样一种原型思想,就是我们所说的RPC远程过程调用。
RPC这种思想最早可以追溯到1976年,RPC的发展到今天已经40年有余了。
如今的计算机应用中,单机性能上很难承受住产品的压力,需要不断扩充多台机器来提升整体的性能。同时为了充分利用这些集群里的计算机,需要对其从架构上进行划分,以提供不同的服务,服务间相互调用完成整个产品的功能。RPC就能帮助我们解决这些服务间的信息传递和调用。
关于RPC的概念,我们可以从广义和狭义来分别进行理解。
我们可以将所有通过网络来进行通讯调用的实现统称为RPC。
按照这样来理解的话,那我们发现HTTP其实也算是一种RPC实现。
区别于HTTP的实现方式,在传输的数据格式上和传输的控制上独立实现。比如在机器间通讯传输的数据不采用HTTP协议的方式(分为起始行、header、body三部份),而是使用自定义格式的二进制方式。
我们更多时候谈到的RPC都是指代这种狭义上的理解。
相比于传统HTTP的实现而言:
优点
缺点
——> HTTP更多的面向用户与产品服务器的通讯。面向大众的
——> RPC更多的面向产品内部服务器间的通讯。 thrift。更多的是公司内部之间 ,各个系统的调用,高效便捷
方式一: X 本地调用
方式二: HTTP调用
把推荐系统当做单独的一个小项目,独立运行部署,web直接调用
耦合性很低
网络调用
由推荐系统封装HTTP 接口,在web中发起http请求进行调用
缺点 HTTP的效率低下
```
GET http://192.168.10.4:8000/recomment HTTP/1.1
....
body
```
方式三: RPC调用 远端过程调用
Thrift
gRPC
方案 传输的数据 协议 protobuf
RPC的设计思想是力图使远程调用中的通讯细节对于使用者透明,调用双方无需关心网络通讯的具体实现。因而实现RPC要进行一定的封装。
流程:
简介
gRPC是由Google公司开源的高性能RPC框架。
gRPC支持多语言
gRPC原生使用C、Java、Go进行了三种实现,而C语言实现的版本进行封装后又支持C++、C#、Node、ObjC、 Python、Ruby、PHP等开发语言
gRPC支持多平台
支持的平台包括:Linux、Android、iOS、MacOS、Windows
gRPC的消息协议使用Google自家开源的Protocol Buffers协议机制(proto3) 序列化
C语言实现的gRPC支持多语言,其架构如下
Protocol Buffers 是一种与语言无关,平台无关的可扩展机制,用于序列化结构化数据。使用Protocol Buffers 可以一次定义结构化的数据,然后可以使用特殊生成的源代码轻松地在各种数据流中使用各种语言编写和读取结构化数据。
现在有许多框架等在使用Protocol Buffers。gRPC也是基于Protocol Buffers。 Protocol Buffers 目前有2和3两个版本号。
在gRPC中推荐使用proto3版本。
1) Protocol Buffers版本
Protocol Buffers文档的第一行非注释行,为版本申明,不填写的话默认为版本2。
syntax = "proto3";
或者
syntax = "proto2";
2)Package包
Protocol Buffers 可以声明package,来防止命名冲突。 Packages是可选的。
package foo.bar;
message Open { ... }
使用的时候,也要加上命名空间,
message Foo {
...
foo.bar.Open open = 1;
...
}
注意:对于Python而言,package会被忽略处理,因为Python中的包是以文件目录来定义的。
3)导入
Protocol Buffers
中可以导入其它文件消息等,与Python的import类似。
import “myproject/other_protos.proto”;
4)定义各种消息和服务
消息messge是用来定义数据的,服务service是用来gRPC的方法的。
其实,Protocol Buffers
是一种IDL(交互式数据语言),类似于一种脚本,编译后生成对应的后台接口
在首页中 获取特定用户的推荐文章列表 需要web系统和推荐系统配合
在Web系统中
构建客户端请求首页数据的接口
GET /articles?channel_id=10
class ArticleListResource(Resource):
def get(self):
channel_id
user_id
# 调用推荐系统的接口 获取推荐文章id
ret = recommend_article(channel_id, user_id) 方式一
ret = urllib.reqeust('http://192.168.10.4:8000/recomment') 方式二
# 查询缓存或数据库 获取文章的具体信息( 通过我们自己分装的缓存工具类)
。。
return
方式一: X 本地调用
方式二: HTTP调用
把推荐系统当做单独的一个小项目,独立运行部署,web直接调用
耦合性很低
网络调用
由推荐系统封装HTTP 接口,在web中发起http请求进行调用
缺点 HTTP的效率低下
GET http://192.168.10.4:8000/recomment HTTP/1.1
....
body
方式三: RPC调用 远端过程调用
声明RPC调用的接口形式
ret = recommend_article(channel_id, user_id)
接口的名字 recommend_article
调用时传递的参数 int channel_id , int user_id
接口返回数据 int list [article_id, article_id, ....]
生成 调用的代码 (包含了 参数转换为二进制传输的方法、网络传输收发的方法)
rpc框架会提供生成代码的工具 (编译器)
使用编译器生成不同语言的代码
调用方 python -> 使用编译器 根据上面的接口描述 ,生成python代码
被调用方 java -> 使用编译器 根据上面的接口,生成java代码
需要补充代码
在被调用的一端 服务端 补充被调用时执行的逻辑函数
在调用的一方,需要在 调用的代码地方 补充上调用的代码