MyRpc
项目源码GitHub地址:https://github.com/Ye2273/MyRpc
RPC通信原理
两台服务器通信, 调用 对方的 函数方法:
- 将 函数名 和 参数 要 进行 打包 —–序列化
- 打包好后,通过网络 进行传输(muduo库实现
- 另一方 接收到 打包的 数据 进行 解包——反序列化
环境配置
编译环境:Linux
语言:C++
工具:muduo库、CMake、Protobuf、ZooKeeper
protobuf
google 提供了protobuf多种语言的实现:java、c#、c++、go 和 python,每一种实现都包含了相应语言的编译器以及库文件。
可以把它用于分布式应用之间的数据通信或者异构环境下的数据交换。作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。
message 定义的类型是专门用作 RPC 参数和 返回值的序列化和反序列化
这些 类型都是从Message 继承来的
定义了描述rpc 方法的服务类 通过 protoc 生成 两个类
- rpc 服务提供者(真正执行rpc方法的一端
- 从protobuf提供的Service 类 继承来的
- 两个rpc方法的虚函数
- 一个 GetDescriptor()的指针 可以获取 服务的名字以及方法名
- rpc服务消费者(调用方的代理类,我的所有方法都交给他实现(stub
- 定义对象传给RpcChannel,是个抽象类
- 在这里 不管调用 哪个 自定义的 方法(login,getfriend)都是 调用 channel->callmethod 方法
- 抽象方法callMethod(纯虚函数)
- 所以RpcChannel本身是无法 实例化对象的
- 我们需要 自己实现一个 类 继承 RpcChannel,实现 具体的callMethod方法
服务方业务流程
框架 RpcProvider 要 实现 三个 部分
- muduo实现网络传输功能
- 调用muduo的api 实现请求从远端到达服务端的网络部分
- protobuf 实现 数据的序列化和反序列化
- 将通过 muduo 网络传输过来的请求 进行序列化传给服务方法,生成响应后再反序列化传给 muduo 发送出去
- 设置一张服务对象与服务方法的映射表:
- 当请求调用框架的时候,让框架明白需要调用的是哪个方法
- 当请求调用框架的时候,让框架明白需要调用的是哪个方法
1、Provider 启动网络服务
MyRpcApplication 初始化:
读取配置文件ip、port
将 参数 信息 存进了 一个 conf 对象中
然后在 推送rpc服务的提供者 启动rpc 服务节点
建立用 conf 中的 信息 建立网络 连接,就是 设置muduo库的步骤
这样就启动了 rpc 远程调用的网络服务
调用方就 能根据 tcp 连接 调用 rpc 服务了。
2、Provider 发布rpc服务接口,供外部使用(NotifyService
NotifyService 设置映射表记录 — 服务对象 :服务方法
从而让框架知道接收到服务请求时应该 调用哪个服务节点的 哪个服务方法
(代码截图看不清就去看源码吧~~
调用方
日志模块
一个简易的异步日志系统
zookeeper
1.1 什么是Zookeeper
- ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是大数据生态中的重要组件。它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
- 它是一个为分布式应用提供一致性协调服务的中间件
1.2 ZooKeeper提供了什么
- 文件系统
- Zookeeper提供一个多层级的节点命名空间(节点称为znode)。与文件系统不同的是,这些节点都可以设置关联的数据,而文件系统中只有文件节点可以存放数据而目录节点不行。Zookeeper为了保证高吞吐和低延迟,在内存中维护了这个树状的目录结构,这种特性使得Zookeeper不能用于存放大量的数据,每个节点的存放数据上限为1M。
- 通知机制
- client端会对某个znode建立一个watcher事件,当该znode发生变化时,这些client会收到zk的通知,然后client可以根据znode变化来做出业务上的改变等。
分布式系统的问题
- 服务的动态注册和发现,为了支持高并发,OrderService被部署了4份,每个客户端都保存了一份服务提供者的列表,但这个列表是静态的(在配置文件中写死的),如果服务的提供者发生了变化,例如有些机器down了,或者又新增了OrderService的实例,客户端根本不知道,想要得到最新的服务提供者的URL列表,必须手工更新配置文件,很不方便。
在网络中服务都是单独部署的
并不知到对应 的 服务 节点 部署在哪里,如果 使用静态的配置文件 就会 发生 上的 问题
所以 需要 一个 服务注册中心
解决方案:
解除耦合,增加一个中间层 – 注册中心它保存了能提供的服务的名称,以及URL。首先这些服务会在注册中心进行注册,当客户端来查询的时候,只需要给出名称,注册中心就会给出一个URL。所有的客户端在访问服务前,都需要向这个注册中心进行询问,以获得最新的地址。
-
注册中心可以是树形结构,每个服务下面有若干节点,每个节点表示服务的实例。
-
注册中心和各个服务实例直接建立Session,要求实例们定期发送心跳,一旦特定时间收不到心跳,则认为实例挂了,删除该实例。
-
临时节点会删掉,永久节点不会删
分布式锁, 多台机器上运行的不同的系统操作同一资源(分布式环境中!!
安装使用框架
在Linux环境中:
将 lib中的静态库文件 放在 usr/lib 或者 usr/local/lib
include中的所有头文件放在 usr/include 或者 usr/local/include
这样用的时候就能默认调用到。
参考资料
https://www.cnblogs.com/xinyonghu/p/11031729.html