Skip to content

Support per-peer client local IP/device binding for multihomed channels #3260

@hjwsm1989

Description

@hjwsm1989

Is your feature request related to a problem?

是的。

brpc 目前已经开始支持将 client 连接绑定到指定的本地 IP / device(可参考 PR #3179),但这只覆盖了“一个 Channel 使用一个固定本端出口”的场景。

这对于多网卡、多平面网络的应用还不够,典型场景包括:

  • server 侧有多个地址(例如 private/public,或多个 private plane)
  • 同一个 client Channel 可能通过 naming service / load balancer 访问不同 peer
  • 不同 remote peer 需要使用不同的本地 IP + device 绑定

一个具体故障场景是:

  • private 网卡已经 down
  • OS 仍然可能通过其他可用网卡把报文路由到其他节点的 private IP
  • 心跳仍能到达 peer 的 private endpoint
  • 上层健康检查逻辑无法正确识别 private 网络已经失效

在这种场景下,我们期望的是 fail fast,而不是让 OS 静默地通过别的网卡绕行。

Describe the solution you'd like

希望 brpc 支持 按 peer 选择 client 本地绑定策略,而不是仅支持“一个 Channel 绑定一个固定的本端出口”。

也就是说,brpc 应该能够在“为某个目标 peer 创建 socket 之前”,先决定这次应该使用哪个本地绑定目标,然后对该 peer 对应的 socket 执行:

  • 本地 source IP 绑定(bind(local_ip, 0)
  • 网卡绑定(Linux 下的 SO_BINDTODEVICE

从设计上看,关键点是:

  • bind 决策应发生在 Channel / naming-service / socket-creation 这一层
  • 而不是在 Socket::Connect() 内部做晚期、临时的推导

更适合的抽象模型可能是:

  • peer selector -> local_ip@device

其中 peer selector 可以是:

  • 精确 peer endpoint
  • CIDR
  • 默认 / fallback 规则

希望满足的行为包括:

  • single / pooled / short 三种连接类型行为一致
  • 对 naming service / 多 server 地址场景有效
  • 派生 socket(pooled/short)能够继承相同 bind 策略
  • 不同 bind 策略不会错误复用同一个底层 socket
  • 当配置的本地出口不可用时,应直接失败,而不是被 OS 自动改道

Describe alternatives you've considered

  1. 一个 Channel 只绑定一个固定本地出口

    • 这是当前单 bind 模型能支持的方式
    • 但当一个 Channel 面向多个 peer,且不同 peer 必须走不同出口时,这种模型不够
  2. 应用层拆多个 Channel

    • 可以绕过问题,但会把网络拓扑策略下沉到每个应用里
    • 对 naming service / 动态地址场景也不够自然,应用维护成本较高
  3. Socket::Connect() 中动态推导 device

    • 这个决策点太晚
    • 也会让 pooled / 派生 socket 的行为更难推理和保证一致性
  4. 把 local device 编码进 server endpoint 字符串中(例如 ip:port@device

    • 这种做法会把远端 server 属性和本端 client 属性混在一起
    • 很难优雅扩展到 CIDR、默认规则等场景

Additional context/screenshots

这个需求来自真实的多网卡部署场景:server private 地址与 client 本地出口之间必须显式匹配。

PR #3179 是很好的基础,但对于“多地址 / naming-service 驱动 / 同一 Channel 面向多个 peer”的场景,还需要进一步支持 按 peer 选择本地 bind 策略

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions