RPC
(Remote Procedure Call Protocol)远程过程调用协议,用于实现跨网络的进程间通信。它提供了一种简单高效的方式,使得分布式系统中的不同组件能够像调用本地函数一样调用远程函数。本篇博客将介绍RPC的基本概念,适用场景,技术特点,常见的技术实践举例,历史框架如CORBA,以及近几年RPC在Java、Go、C++和Python中的实践案例,并展望未来RPC的发展前景。
RPC特点
- RPC协议:目前典型的RPC实现包括:Dubbo、Thrift、GRPC、Hetty等。
- 网络协议和网络IO模型透明:RPC客户端认为自己是在调用本地对象,无需关心传输层使用的什么传输协议。
- 信息格式透明:被调用的对象内部是如何使用传入的参数,并得出调用方想要的结果的,调用方不用关心的(“”透明"通常指的是一种操作或过程对用户或其他系统的影响被隐藏或减轻到最小程度,以使其表现为无缝、不可察觉或无需用户干预。 这种透明性的目标是使系统更易于使用、更具可靠性,并减少对终端用户或其他系统组件的干扰)。
- 跨语言能力:调用方无需知道远程服务器的应用程序是使用什么语言运行的。无论服务器方使用的是什么语言,本次调用都应该成功,并且返回值也应该按照调用方程序语言所能理解的形式进行描述。
- 可扩展性强: 支持服务发现、负载均衡、集群调用等功能,方便系统扩展。
适用场景
RPC在分布式系统中有广泛的应用场景,广泛应用于需求频繁的跨网络调用场景,如微服务架构中的服务调用、分布式计算和数据分析中的远程调用等。包括但不限于以下几个方面:
- 微服务架构:RPC可以实现微服务之间的通信,各个微服务可以独立部署和扩展。
- 跨语言通信:RPC可以解决不同语言之间的通信问题,使得不同语言编写的服务可以互相调用。
- 分布式计算:RPC可以用于分布式计算任务的调度和协调,提高计算资源的利用率。
- 高性能网络传输:RPC可以通过优化网络传输协议和序列化机制,提高数据传输的效率和性能。
为什么使用RPC
正如上节所说,在我们部署到分布式系统的时候,对于大型项目,很多的功能已经无法简单的划分开来,甚至根本无法划分出来。此时,可以将公共业务逻辑抽离出来,将之组成独立的服务Service应用 。而原有的、新增的应用都可以与那些独立的Service应用交互,以此来完成完整的业务功能。这时,RPC就可以实现这样的需求大。
RPC在项目中实现的功能
mprpc框架主要包含以下两个部分的内容:
- 黄色部分:设计rpc方法参数的打包和解析,也就是数据的序列化和反序列化,使用Protobuf,使用json也行,但是Protobuf是二进制存储的,且不需要存储额外的信息"zhangsan"“123456”;而xml和json是文本存储的,且json需要存储键值对,name:“zhangsan”.pwd:“123456”,在[分布式网络通讯框架]----Protobuf安装配置–附带每一步截图中,详细介绍了为什么使用protobuf。
- 绿色部分:网络部分,包括寻找rpc服务主机,发起rpc调用请求和响应rpc调用结果,使用muduo网络库和zookeeper服务配置中心(专门做服务发现)。
项目代码工程目录
- bin:可执行文件
- build:项目编译文件
- lib:项目库文件
- src:源文件
- test:测试代码
- example:框架代码使用范例
- CMakeLists.txt:顶层的cmake文件
- README.md:项目自述文件
- autobuild.sh:一键编译脚本
使用Protobuf
- protobuf有自己的数据类型,但是含义基本和c++相同。
- 尽量使用bytes来代替字符串string,减少字节和字符间的编码转化。
- message生成以后相当于就是类,不仅仅可以定义普通的简单的类型,还可以定义组合对象,以及repeated组合,map<>映射表,枚举等等
<pre>syntax ="proto3"; //声明了protobuf的版本
package fixbug;//声明了代码所在的包(对于c++来说就是namespace)
message ResultCode
{
int32 errcode=1;
bytes errmsg=2;
}
message GetFriendListResponse
{
ResultCode result=1;
repeated User friend_list=2; //定义了一个列表类型
}
- 编写xxx.proto文件,在终端利用
proto xxx.proto --cpp_out=./
进行编译,会生成xxx.pb.cc以及xxx.pb.h文件,与xxx.proto文件中的类型相对应。