brpc中后端server挂在同一个命名服务和不同命名服务的区别详解

发布于:2025-07-09 ⋅ 阅读:(16) ⋅ 点赞:(0)

核心概念:命名服务 (Naming Service)​

在分布式系统和RPC框架(如bRPC)中,​命名服务(Naming Service)​​ 扮演着服务地址注册与发现的角色。它维护着一个映射关系:​服务名 -> 一组提供该服务的服务器实例(Endpoint列表)​

  • 例如:​​ 一个服务名叫 SearchService,在命名服务(如Nacos, ZooKeeper, Consul, bRPC内置的DNS/File等)中注册了3个服务器地址:192.168.1.101:8000, 192.168.1.102:8000, 192.168.1.103:8000
  • Channel的作用:​​ 在bRPC中,一个 Channel 对象通常对应一个服务名。当你初始化一个Channel时,给它配置一个命名服务地址和该服务名,这个Channel就能自动地从命名服务获取到当前所有可用的服务器Endpoint列表,并负责后续的负载均衡(如轮询、随机等)、连接管理、健康检查等工作。

区别详解

  1. 后端server挂在同一个命名服务内
  • 含义:​​ 所有提供相同逻辑服务的后端服务器实例(Server),都注册在同一个服务名下,位于同一个命名服务中。
  • 示例:​​ 如上所述,所有 SearchService 的服务器实例都注册在命名服务的 SearchService 条目下。
  • bRPC备份请求实现:​
    • 使用单个 Channel 对象即可。这个Channel配置了指向该服务名和命名服务。
    • ChannelOptions 中设置 backup_request_ms = X(例如2ms)。
    • 工作流程:​
      1. 客户端通过这个Channel发起RPC调用。
      2. 负载均衡器(如轮询)​选择列表中的一个Server(假设叫Server A)​发送第一个请求。
      3. 如果X 毫秒后,第一个请求(发给Server A)​还没有返回响应​:
      4. bRPC框架自动触发备份请求
      5. 负载均衡器再次从当前可用的Server列表中选择另一个Server(假设叫Server B)​​(通常不会是A,但负载均衡策略决定)发送同一个请求的副本
      6. 哪个Server(A或B)先返回有效响应,客户端就使用哪个响应。​​ 后到的响应会被忽略(或根据框架内部机制处理)。
    • 优点:​
      • 简单:​​ 只需配置一个Channel。
      • 高效:​​ ​大部分情况下​(在 backup_request_ms 设置合理时),只会发送一个请求(Server A响应及时)。只有少数慢请求会触发备份请求,因此平均请求量接近1倍,对后端集群压力小。
      • 透明:​​ 负载均衡、服务发现、连接管理都由Channel自动处理。
    • 适用场景:​​ ​同一个集群内部,通过增加冗余请求提高服务可用性(容错单机慢节点或瞬时故障)。
  1. 后端server不能挂在一个命名服务内
  • 含义:​​ 提供相同逻辑服务的后端服务器实例,​不属于同一个逻辑集群,或者物理/逻辑上完全隔离​(如两个不同的IDC机房、两个不同的云厂商、两个独立部署的异构系统)。因此,它们无法(或不适合)注册在同一个服务名下的同一个命名服务中
  • 示例:​
    • 主集群 SearchService-A (注册在命名服务A)。
    • 备份集群 SearchService-B (注册在命名服务B,或同一个命名服务的另一个服务名)。
    • 或者两个完全独立的不同服务(如 Service-XService-Y),但客户端需要它们互备。
  • bRPC备份请求实现 - 推荐方法 (SelectiveChannel):​
    • 使用一个 SelectiveChannel 对象作为主访问点。
    • 每一个独立的集群/服务创建一个子Channel (sub Channel)​​:
      • 子Channel1:配置指向集群A的服务名/命名服务 (如 SearchService-A)。
      • 子Channel2:配置指向集群B的服务名/命名服务 (如 SearchService-B)。
    • 将这些子Channel ​Add​ 到 SelectiveChannel 中。
    • SelectiveChannelChannelOptions 中设置 backup_request_ms = X(例如2ms)。
    • 工作流程:​
      1. 客户端通过 SelectiveChannel 发起RPC调用。
      2. SelectiveChannel ​选择其中一个子Channel(假设是子Channel1,对应集群A)​​ 发送第一个请求。
      3. 如果X 毫秒后,第一个请求(发给集群A)​还没有返回响应​:
      4. bRPC框架自动触发备份请求
      5. SelectiveChannel ​选择另一个子Channel(即子Channel2,对应集群B)​​ 发送同一个请求的副本
      6. 哪个子Channel(即哪个集群)先返回有效响应,客户端就使用哪个响应。​
    • 优点:​
      • 实现了跨集群/跨服务的互备。一个集群整体故障或网络分区时,备份请求能打到另一个可用集群。
      • 继承了核心备份请求机制的高效性:合理设置 backup_request_ms 后,​大部分请求也只发往一个集群(主集群),平均请求量接近1倍
      • 结构清晰,易于管理不同的后端源。
    • 适用场景:​​ ​跨机房容灾、多活部署、异构系统互备。需要确保一个集群完全不可用时,服务仍能降级运行。
  • 不推荐方法 (Join + Cancel):​
    • 手动创建两个独立的Channel:ChannelA(指向集群A),ChannelB(指向集群B)。
    • 同一个请求,​同时异步发起两个RPC调用:一个通过ChannelA发往集群A,另一个通过ChannelB发往集群B。
    • 使用 Join 等待任意一个完成。
    • 在各自的 done 回调中,​取消 (Cancel)​​ 另一个还在进行中的RPC。
    • 缺点:​
      • 总是发送两个请求,无论第一个请求是否快速响应。这导致对后端的压力是2倍,非常不经济。
      • 需要手动管理取消逻辑,代码复杂。
      • 无法利用到bRPC内置的备份请求优化机制。
    • 文档态度:​​ 明确标注“不推荐”、“你应该尽量避免用这个方法”。

总结对比表

特性 同一个命名服务 (单Channel) 不同命名服务 (SelectiveChannel) 不同命名服务 (Join+Cancel - 不推荐)
后端关系 同一集群内服务器 不同集群/异构服务 (互备) 不同集群/异构服务 (互备)
bRPC对象 单个 Channel 一个 SelectiveChannel + 多个 sub Channel 多个独立的 Channel
配置备份请求 ChannelOptions.backup_request_ms SelectiveChannelOptions.backup_request_ms 无内置机制,需手动实现
请求发送策略 先发集群内一台,超时发集群内另一台 先发一个集群,超时发另一个集群 同时发往所有目标集群
平均请求量 ~1倍 (合理设置 backup_request_ms 时) ~1倍 (合理设置 backup_request_ms 时) 总是2倍​ (或更多)
后端压力 高 (2倍)​
主要优势 容错单机慢节点/瞬时故障,高效 实现跨集群/服务互备,高效 能实现互备 (但代价高)
主要劣势 无法应对整个集群故障 配置略复杂 效率低,压力大,代码复杂
适用场景 同集群高可用 跨集群容灾/多活/异构互备 应避免使用
文档推荐度 推荐 推荐 不推荐

关键点强调

  • 命名服务的核心作用:​​ 它定义了“哪些服务器属于同一个逻辑服务/集群”。同一个命名服务下的同一个服务名,意味着这些服务器是可以互相替代、负载均衡的。
  • 备份请求的本质:​​ 是一种超时驱动的冗余请求机制,旨在通过发送少量额外请求(主要在超时后)来掩盖个别节点的慢响应或瞬时故障,提升请求成功率(SLA)和降低尾部延迟(Latency Tail)。
  • ​**backup_request_ms 的智慧:​**​ 合理设置这个阈值是高效的关键。设置得太小,会过早触发不必要的备份请求,增加压力;设置得太大,备份请求的降延迟效果就不明显。文档建议通过延时分布(如 latency_cdf 图)来观察和选择,目标是覆盖大部分请求(如95%或99%),让备份请求只在少数慢请求上触发。
  • SelectiveChannel vs Join+Cancel:​​ SelectiveChannel 巧妙地将“选择不同源”和“备份请求”机制结合起来,​在提供跨集群互备能力的同时,最大程度地保留了备份请求的高效性(平均接近1倍请求)​。而Join+Cancel简单粗暴地发双份请求,效率低下,是文档明确反对的方案。

Reference

  1. brpc documentation

网站公告

今日签到

点亮在社区的每一天
去签到