10分钟带你了解RPC 架构的基本结构( 二 )

  • RpcProxy , 远程 API 的代理实现 , 提供远程服务本地化访问的入口
  • RpcCaller , 负责编码和发送调用请求到服务方并等待结果
  • RpcConnector , 负责与服务端建立通信通道并发送请求到服务端
  • 服务端组件与职责包括:
    • RpcServer , 负责实现远程 API
    • RpcInvoker , 负责调用服务端的具体实现并返回结果
    • RpcProcessor , 负责对请求进行处理 , 高效控制调用过程
    • RpcAcceptor , 负责接收客户方请求并返回请求结果
    而客户端和服务器端所共有的组件包括:
    • RpcProtocol , 负责网络传输协议的编码和解码
    • RpcChannel , 负责建立和维护网络数据传输通道
    这样 , 我们对一个典型 RPC 架构中的基本结构和组件就有了完整的了解 。那么 , 如果我们想要实现这个架构 , 需要构建怎样的技术体系呢?
    RPC 架构的技术体系我们都知道 , 架构是一种设计上的思想和方法 , 明白了它的基本结构和组成部分之后 , 我们就可以进一步梳理想要实现 RPC 架构的技术体系 , 包括网络通信、序列化、传输协议和远程调用 。
    网络通信我们先来看网络通信 。网络通信的涉及面很广 , 对于 RPC 架构而言 , 一方面我们会重点关注性能 , 所以势必要考虑基于 TCP 等特定协议的网络连接方式和 IO 模型;另一方面 , 我们也需要考虑可靠性 , 因为这样才能确保远程调用过程的稳定 。
    好 , 下面我们就具体来看看 。
    首先是性能问题 。一般来说 , 基于 TCP 协议的网络连接有两种基本方式:长连接和短连接 。长连接和短连接的本质区别是连接的创建和关闭策略 , 长连接可以复用现有连接 , 而短连接则能够更快地释放资源 。这两者本身各有利弊 , 而在 RPC 框架的实现过程中 , 考虑到性能和服务治理等因素 , 我们通常是使用长连接进行通信 , 典型的实现框架就是 Dubbo 。
    而对于 IO 模型 , 最简单、最基础的网络 IO 模型就是阻塞式 IO , 即 BIO(Blocking IO) 。BIO 要求客户端请求数与服务端线程数一一对应 , 但是显然 , 由于线程的创建需要消耗系统资源 , 在分布式系统中 , 服务端可以创建的线程数将会成为系统的瓶颈 。
    因此 , 在 RPC 架构中 , 我们通常都会使用非阻塞 IO , 即 NIO(Non-blocking IO)技术来提供性能 。基于 NIO 模式下的多路复用机制 , 创建少数的线程就能对大量请求进行高效的响应 。
    然后是针对可靠性问题 , 由于存在网络闪断、超时等与网络状态相关的不稳定性因素 , 以及业务系统本身的故障 , 网络之间的通信就必须在发生上述问题时能够快速感知并修复 。常见的网络通信保障手段 , 包括链路有效性检测及断线之后的重连处理等 。这些机制都比较常见 , 也不是我们讨论的重点 , 这里就不做具体展开了 。
    序列化而如果我们想要在网络上传输数据 , 就需要用到数据序列化技术了 。
    目前业界成熟的序列化工具已经有很多 , 常见的 XML 和 JSON 就是文本类序列化方式的代表 , 它们可以让数据以开发人员可读的方式进行传输 。还有一种基于二进制实现的方案 , 包括 google 的 Protocol Buffer 和 Facebook 的 Thrift 。
    那么 , 我们在选择序列化工具时 , 应该考虑什么呢?一个关键指标就是性能 。
    性能指标主要包括空间复杂度、时间复杂度以及 CPU/ 内存资源占用等 。我在下表列举了目前主流的一些序列化技术 , 供你参考:
    10分钟带你了解RPC 架构的基本结构

    文章插图
    可以看到 , 在时间维度上 , Alibaba 的 fastjson 具有一定优势;而从空间维度上看 , 相较其他技术 , 你可以优先选择 Protocol Buffer 。
    传输协议我们知道 , 但凡涉及通过网络来传输数据 , 就一定要采用某种传输协议 。在 ISO/OSI 的 7 层网络模型中 , RPC 架构的设计和实现通常会涉及传输层及以上各个层次的相关协议 , 我们所熟悉的 TCP 协议就属于传输层 , 而 HTTP 协议则位于应用层 。


    推荐阅读