RPC

RPC(Remote Procedure Call) : 远程过程调用

多路复用的优化

RPC 提供的是远程方法的调用,但本质上是数据的传递,传递数据有一个最基本的问题要处理,就是提升吞吐量(单位时间传递的数据量)。如果为每个远程调用(请求)建立一个连接,就会造成资源的浪费,因此通常我们会考虑多个请求复用一个连接,叫作多路复用

rpc_切片传输

切片传输的方案在这之上,将数据切片可以保证大、小任务并行,不会因为大任务阻塞小任务。

注册发现

上线一个服务的时候,就在 Redis 的某个hash对象中存储它和它对应的 IP 地址 + 端口列表

通常我们将写这个hash对象的过程,也就是服务被记录的过程称作注册。我们远程调用一个 RPC 服务的时候,调用端提供的是 RPC 服务的名称(例如:命名空间+对象+方法),根据名称查找到提供服务的 IP + 端口清单并指定某个 IP + 端口(提供服务)的过程称作发现

比如基于 Redis 的实现,如果所有 RPC 调用都需要去 Redis 查询,会造成负责发现的中间件压力较大。实际的操作过程中,往往会增加缓存。也就是 RPC 调用者会缓存上一次调用的 IP + 端口。但是这样设计,缓存又可能会和注册表之间产生数据不一致的问题。这个时候,可以考虑由分布式共识服务比如 ZooKeeper 提供订阅,让 RPC 调用者订阅到服务地址的变更,及时更新自己的缓存。

设计注册和发现两个功能的最大的价值是让客户端不再需要关注服务的部署细节,这样方便在全局动态调整服务的部署策略。

负载均衡

发现阶段拿到的是一份 IP + 端口清单,从清单里挑一个的过程就是负载均衡。常见策略:

  1. 轮询与加权轮询:实现简单,加权可以照顾配置不同的机器
  2. 随机与加权随机:无状态,适合调用量大的场景
  3. 最少连接数:把请求给当前压力最小的节点,需要维护连接计数
  4. 一致性哈希:同一个 key 尽量落到同一节点,缓存类服务常用,扩缩容时迁移量小

RPC 的负载均衡通常做在调用端(客户端负载均衡):调用端本地就有服务清单,选完直连目标节点,比经过一层网关少一跳。

可用性和容灾

调用端选出的节点未必健康,所以还需要这几层保障:

  1. 健康检查:定期探测节点,不健康的从本地清单里摘掉
  2. 超时与重试:给每次调用设超时,失败后换一个节点重试;注意重试要求接口幂等,否则会重复扣款这类问题
  3. 熔断:某个节点或服务连续失败到一定比例就直接快速失败,不再发起真实调用,给下游恢复的时间
  4. 降级:熔断之后返回兜底数据或缓存值,保证主流程不被拖垮
  5. 限流:在服务端侧限制单位时间的请求量,避免被突发流量打穿