📃个人主页:island1314
🔥个人博客:island
⛺️ 欢迎关注:👍点赞 👂🏽留言 😍收藏 💞 💞 💞
- 生活总是不会一帆风顺,前进的道路也不会永远一马平川,如何面对挫折影响人生走向 – 《人民日报》
🔥 目录
- 一、项目介绍
- 二、技术选型
- 2.1 RPC 实现方案
- 2.2 网络传输的参数和返回值怎么映射到对应的RPC接口上?
- 方法一:使用 protobuf 的反射机制
- 方法二:使用 C++ 模板、类型萃取、函数萃取等机制
- 方法三:使用更通用的类型(如 JSON)
- 🌈 技术方案对比
- 2.3 网络传输怎么做?
- 2.4 序列化和反序列化?
- 三、环境搭建
- 3.1 Centos 7.6 环境搭建
- 3.2 Ubuntu 22.04 环境搭建
一、项目介绍
🔥 RPC(Remote Procedure Call)
远程过程调用,是一种通过网络从远程计算机上请求服务,而不需要了解底层网络通信细节。
RPC
可以使用多种网络协议进行通信,如HTTP、TCP、UDP等,并且在TCP/IP
网络四层模型中跨越了传输层和应用层。简言之RPC就是像调用本地方法一样调用远程方法- 过程可以理解为业务处理、计算任务,更直白的说,就是程序/方法/函数等,就是像调用本地方法一样调用远程方法
💬 通俗类比:通信方式的进化
+ 本地调用:情侣同城约会- 随时见面(低延迟)- 直接交流(无需协议)+ RPC调用:跨国网恋奔现 ✈️ 约定时间(服务发现)📨 发送航班信息(序列化)🛃 海关检查(协议校验)💌 最终见面(反序列化)
一个完整RPC通信框架,大概包含以下内容
- 序列化协议
- 通信协议
- 连接复用
- 服务注册
- 服务发现
- 服务订阅和通知
- 负载均衡
- 服务监控
- 同步调用
- 异步调用
我们的项目是基于C++、JsonCpp、muduo网络库实现一个简单、易用的RPC通信框架,即使是不懂网络的开发者也可以很快速的上手,它实现了同步调用、异步
callback
调用、异步futrue
调用、服务注册/发现,服务上线/下线以及发布订阅等功能设计。
二、技术选型
2.1 RPC 实现方案
目前RPC的实现方案有两种:
-
client
和server
继承公共接口- 根据
IDL
(接口描述语言)定义公共接口 - 编写代码生成器根据IDL语言生成相关的C++、Java代码然后我们的客户端和服务器程序共同向上继承公共接口即可
- 比如:我们常用的Protobuf、ison可以定义IDL接口,并生成RPC相关的代码
- 缺点:使用pb因为生成一部分代码,所以对理解不够友好;如果是json定义IDL语言 需要自己编写代码生成器难度较大一点,暂不考虑这种方案
- 根据
-
实现⼀个远程调用接口cal,,然后通过传入函数名参数来调用RPC接口,我们采用这种实现方案
2.2 网络传输的参数和返回值怎么映射到对应的RPC接口上?
方法一:使用 protobuf 的反射机制
原理
protobuf
是一种高效的序列化协议,支持通过 .proto
文件定义数据结构。protobuf
提供了反射机制,允许程序在运行时动态获取消息的字段信息(如字段名、类型等)。通过反射机制,可以将网络传输的参数和返回值动态映射到对应的RPC接口。
实现步骤
- 定义
.proto
文件 :描述RPC接口的请求和响应数据结构。 - 生成代码 :使用
protoc
工具生成对应语言的代码(如C++、Python等)。 - 利用反射机制 :
- 在运行时,通过反射机制解析请求和响应的字段。
- 动态调用对应的RPC接口,并将解析后的数据作为参数传递。
- 序列化和反序列化 :将请求和响应数据序列化为二进制格式进行传输。
优点
- 高效:
protobuf
序列化效率高,占用带宽小。 - 强类型:编译时检查字段类型,减少运行时错误。
- 易扩展:通过
.proto
文件轻松扩展字段。
缺点
- 学习成本较高:需要熟悉
.proto
文件和反射机制。 - 动态性有限:反射机制虽然灵活,但仍需依赖预定义的
.proto
文件。
Mermaid 图
方法二:使用 C++ 模板、类型萃取、函数萃取等机制
原理
C++ 模板元编程允许在编译时对类型进行操作,而类型萃取和函数萃取则用于提取函数的参数和返回值类型。通过这些机制,可以在编译时自动推导出RPC接口的参数和返回值类型,从而实现参数和返回值的映射。
实现步骤
- 定义RPC接口 :使用C++函数定义RPC接口。
- 使用模板萃取 :
- 利用
std::function
或模板函数提取函数的参数和返回值类型。 - 定义通用的包装器(Wrapper),将参数和返回值映射到网络传输的格式。
- 利用
- 序列化和反序列化 :
- 将参数序列化为网络传输格式(如JSON或自定义二进制格式)。
- 在服务端反序列化后,调用对应的RPC接口。
- 返回结果 :将返回值序列化并发送回客户端。
优点
- 高性能:所有类型推导和映射在编译时完成,运行时开销低。
- 灵活性强:支持任意类型的参数和返回值。
- 类型安全:编译时检查参数和返回值类型。
缺点
- 复杂度高:需要熟悉C++模板元编程和类型萃取机制。
- 不易调试:模板代码在编译时展开,调试难度较大。
MerMaid 图
方法三:使用更通用的类型(如 JSON)
原理
JSON 是一种轻量级的数据交换格式,具有良好的可读性和跨语言支持。通过设计一套通用的参数和返回值协议,可以将网络传输的数据统一表示为JSON格式,从而简化参数和返回值的映射。
实现步骤
- 设计协议 :
- 定义请求和响应的JSON结构,包括字段名、类型和含义。
- 例如,请求可能包含
method
(接口名)、params
(参数列表)等字段。
- 序列化和反序列化 :
- 客户端将参数序列化为JSON格式并发送。
- 服务端解析JSON数据,提取参数并调用对应的RPC接口。
- 返回结果 :
- 服务端将返回值序列化为JSON格式并发送回客户端。
优点
- 简单易用:JSON格式直观,易于理解和实现。
- 跨语言支持:几乎所有的编程语言都支持JSON解析。
- 动态性强:无需提前定义固定的数据结构。
缺点
- 性能较低:JSON序列化和反序列化效率低于二进制格式。
- 类型不安全:JSON是弱类型格式,可能导致运行时错误。
MerMaid 图
🌈 技术方案对比
方案 | 核心技术 | 优点 | 缺点 |
---|---|---|---|
Protobuf反射 | 利用.proto 文件的元数据描述 | 强类型安全,跨语言支持 | 需要IDL编译,C++实现较复杂 |
模板元编程 | 类型萃取+函数签名解析 | 零运行时开销,类型严格匹配 | 代码可读性差,调试困难 |
JSON通用协议 | 动态类型系统+预定义协议格式 | 开发简单,易扩展,可视化调试 | 类型安全性需运行时校验 |
- 由于前两种技术难度和学习成本较高,因此这个项目我们使用第三种方式
2.3 网络传输怎么做?
- 原生socket :实现难度较大,暂不考虑
- Boost asio库的异步通信:需要扩展boost库
- muduo库:和当前项目对应,学习开发成本较低
2.4 序列化和反序列化?
Protobuf
:可选JSON
:因为项目需要使用JSON
来定义函数参数和返回值,所以项目中直接采用JSON
进行序列化和反序列化
三、环境搭建
3.1 Centos 7.6 环境搭建
① 安装 wget
sudo yum install wget
② 更新软件源
sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak
sudo wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.reposudo yum clean all # 清理缓存信息
sudo yum makecache
③ 安装 scl 软件源
sudo yum install centos-release-scl-rh centos-release-scl
④ 安装 epel 软件源
sudo yum install epel-release
⑤ 安装 lrzsz 传输工具
sudo yum install lrzsz
rz --version
rz (lrzsz) 0.12.20
⑥ 安装高版本 gcc/g++ 编译器
sudo yum install devtoolset-7-gcc devtoolset-7-gcc-c++
echo "source /opt/rh/devtoolset-7/enable" >> ~/.bashrc
source ~/.bashrc
g++ -v
⑦ 安装 Jsoncpp 库
sudo yum install jsoncpp-devells /usr/include/jsoncpp/json/
assertions.h autolink.h config.h ...
⑧ 安装 cmake
sudo yum install cmakecmake --version
cmake version 2.8.12.2
⑨ 安装 Muduo
- 下载源码
# git⽅式
[zsc@node ~]$ git clone https://github.com/chenshuo/muduo.git
- 修复 muduo 库 安装 protorpc 的时候没有安装
/muduo-master/muduo/net/protorpc/CMakeLists.txt
- 安装依赖环境
sudo yum install make boost-devel
当前上面步骤还是过于多了,我们可以直接 运行脚本编译安装
脚本链接:https://gitee.com/qigezi/bitrpc/blob/master/third/muduo-master.zip
然后把脚本下载之后导入解包,按照下面指令编译安装即可
./build.sh
./build.sh install
3.2 Ubuntu 22.04 环境搭建
① 安装 wget – 一般默认情况下都有
sudo apt-get install wget
② 更新国内软件源
先备份原来的 /etc/apt/source.list 文件
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak# 比如
lighthouse@VM-8-10-ubuntu:~$ sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
lighthouse@VM-8-10-ubuntu:~$ ls /etc/apt/
apt.conf.d keyrings sources.list sources.list.curtin.old trusted.gpg.d
auth.conf.d preferences.d sources.list.bak sources.list.d
添加软件源文件内容,新增以下内容
# 先打开源文件
sudo vi /etc/apt/source.listdeb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
#添加清华源
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse
新增完毕后,更新源
sudo apt-get update
③ 安装 lrzsz 传输工具
sudo apt-get install lrzsz
rz --version
rz (lrzsz) 0.12.20
④ 安装高版本 gcc/g++ 编译器
sudo apt-get install gcc g++
⑤ 安装项目构建工具 make 和 cmake
sudo apt-get install makesudo apt-get install cmake
cmake --version
cmake version 3.22.1
⑥ 安装调试器 gdb
sudo apt-get install gdb
⑦ 安装 git
sudo apt-get install git
git --versio
⑧ 安装 Jsoncpp 库
sudo apt-get install libjsoncpp-dev# 安装成功之后
ls /usr/include/jsoncpp/json/
allocator.h config.h json_features.h reader.h version.h
assertions.h forwards.h json.h value.h writer.h
⑨ 安装 Muduo
- 下载源码
# git⽅式
[zsc@node ~]$ git clone https://github.com/chenshuo/muduo.git
- 安装依赖环境
sudo apt-get install libz-dev libboost-all-dev
运行脚本编译安装
unzip muduo-master.zip
./build.sh
./build.sh install
参考
https://zhuanlan.zhihu.com/p/460646015
https://zhuanlan.zhihu.com/p/33298916
源码:https://github.com/cinemast/libjson-rpc-cpp
value.h writer.h
⑨ 安装 Muduo- 下载源码 ```bash
# git⽅式
[zsc@node ~]$ git clone https://github.com/chenshuo/muduo.git
- 安装依赖环境
sudo apt-get install libz-dev libboost-all-dev
运行脚本编译安装
unzip muduo-master.zip
./build.sh
./build.sh install
参考
https://zhuanlan.zhihu.com/p/460646015
https://zhuanlan.zhihu.com/p/33298916
源码:https://github.com/cinemast/libjson-rpc-cpp
源码:https://github.com/qicosmos/rest_rpc