流程
Client 首先会调用本地的代理,也就是图中的 Proxy。
Client 端 Proxy 会按照协议(Protocol),将调用中传入的数据序列化成字节流。
之后 Client 会通过网络,将字节数据发送到 Server 端。
Server 端接收到字节数据之后,会按照协议进行反序列化,得到相应的请求信息。
Server 端 Proxy 会根据序列化后的请求信息,调用相应的业务逻辑。
Server 端业务逻辑的返回值,也会按照上述逻辑返回给 Client 端。
protocol | RPC 框架的自定义协议 |
---|---|
serialization | 提供了自定义协议对应的序列化、反序列化的相关工具类 |
codec | 提供了自定义协议对应的编码器和解码器 |
transport | 基于 Netty 提供了底层网络通信的功能,其中会使用到 codec 包中定义编码器和解码器,以及 serialization 包中的序列化器和反序列化器。 |
registry | 基于 ZooKeeper 和 Curator 实现了简易版本的注册中心功能 |
proxy | 使用 JDK 动态代理实现了一层代理 |
1.protocol
生产者和消费者协商好使用哪种契约去传输和接受数据。
1.1 基本结构
Header | 版本+消息ID+消息体长度 |
---|---|
message | Header + |
Request | 请求的服务名称+方法+入参类型+参数 |
Response | 响应码+响应结果 |
1.2 协议的编解码
协议的message 中会带有发送方的request ,以及响应方的response , 想要网络传输就需要按照一定规则 ,编码成基本格式去传输。
以Netty为例:
MessageToByteEncoder | 将想要传输的message 序列化为 byte[]数组 用于网络传输 |
---|---|
ByteToMessageDecoder | 将接收到的byte[] 按照 契约 再反序列化为 message 对象 |
2. transport
3.registry
3.1 如何将服务注册上去?
AbstractRegistry 的核心是本地文件缓存的功能。 在 AbstractRegistry 的构造方法中,会调用 loadProperties() 方法将上面写入的本地缓存文件,加载到 properties 对象中。
在网络抖动等原因而导致订阅失败时,Consumer 端的 Registry 就可以调用 getCacheUrls() 方法获取本地缓存,从而得到最近注册的 Provider URL。可见,AbstractRegistry 通过本地缓存提供了一种容错机制,保证了服务的可靠性。
3.2 服务发生变化,消费方如何更新
当 Provider 端暴露的 URL 发生变化时,ZooKeeper 等服务发现组件会通知 Consumer 端的 Registry 组件,Registry 组件会调用 notify() 方法,被通知的 Consumer 能匹配到所有 Provider 的 URL 列表并写入 properties 集合中。