主题
概念卡片:Dubbo集群容错与负载均衡
一句话机制:Dubbo 的集群层把「一堆 Provider 实例」伪装成「一个可调用 Invoker」——调用失败时由 Cluster 容错策略决定怎么处理(重试/忽略/并行/广播),调用前由 LoadBalance 策略从实例列表选一台;默认组合是 Failover(失败重试)+ Random(加权随机)。
集群容错六策略
| 策略 | 行为 | 默认 | 适用场景 |
|---|---|---|---|
| Failover | 失败自动切换其他节点,可配 retries 重试次数 | ✅ 默认 | 读操作;重试带来更长延迟 |
| Failfast | 只调一次,失败立即抛异常 | 非幂等写操作(如新增记录) | |
| Failsafe | 异常记录日志后忽略,返回空结果 | 写审计日志等不关键操作 | |
| Failback | 失败后台记录,定时任务重发(每 5s) | 消息通知 | |
| Forking | 并行调多个 Provider,任一成功即返回(forks="2" 设并行数) | 实时性要求高的读操作;浪费资源 | |
| Broadcast | 逐个广播所有 Provider,任一报错则整体报错 | 通知所有 Provider 更新缓存/本地日志 |
配置示例(服务端/客户端都可配,方法级用 <dubbo:method>):
xml
<dubbo:service retries="2" cluster="failover"/> <!-- 默认就是 failover -->
<dubbo:reference cluster="forking" forks="2"/>读写建议:读操作用 Failover(默认重试 2 次换机器);写操作用 Failfast(幂等重试=0,避免重复写入)。
负载均衡四策略
| 策略 | 机制 | 注意点 |
|---|---|---|
| Random(默认) | 按权重设随机概率(权重平铺区间 + 随机数落点) | 碰撞率高但调用量大时分布均匀,利于动态调权 |
| RoundRobin | 按权重轮询 | 慢提供者请求累积问题:某台慢但没挂,请求卡住越积越多 |
| LeastActive | 选活跃数最少的(请求前 +1,完成后 -1) | 慢提供者活跃数高,自动少接请求 |
| ConsistentHash | 相同参数(默认第一个参数)哈希到同一 Provider | 缺省 160 份虚拟节点;宕机时请求平摊到其他节点不剧烈变动 |
一致性 Hash 参数:
xml
<dubbo:parameter key="hash.arguments" value="0,1"/> <!-- 指定参与 hash 的参数位 -->
<dubbo:parameter key="hash.nodes" value="320"/> <!-- 虚拟节点数 -->协议选型:为什么默认用 dubbo 协议
dubbo 协议 = 单一长连接 + NIO 异步 + TCP + Hessian 二进制序列化,默认推荐。三个经典面试追问:
- 为什么消费者要比提供者多? 单连接有吞吐上限——千兆网卡 128MB/s,经验单连接最多压满约 7MB/s,即 1 个 Provider 约需 20 个 Consumer 才能压满网卡。
- 为什么不能传大包? 假设单包 500KB:单连接 7MB/s ÷ 500KB ≈ 单个 Consumer 对单 Provider 最大 14 TPS;全部带宽 128MB/s 也只 262 TPS——网络成瓶颈。所以 dubbo 协议适合参数 <100K 的小数据量,大文件/超大字符串改用 rmi/http。
- 为什么用异步单一长连接? 服务提供者少、消费者多(如 6 台 Provider 扛上百台 Consumer、1.5 亿次/天);单连接保证单消费者压不垮 Provider,长连接省握手开销,异步 NIO 复用线程池、防 C10K。
协议对比速查:
| 协议 | 连接 | 传输 | 序列化 | 适用 |
|---|---|---|---|---|
| dubbo(推荐) | 单·长 | TCP NIO 异步 | Hessian | 大并发小数据、消费者多 |
| rmi | 多·短 | TCP 同步 | Java 标准 | 常规调用、RMI 互操作;低版本 Commons-Collections 有安全漏洞 |
| hessian | 多·短 | HTTP 同步 | Hessian | 参数大、可传文件、与原生 hessian 互操作 |
| http | 多·短 | HTTP 同步 | 表单/JSON | 需同时给浏览器 JS 调用 |
| webservice | 多·短 | HTTP 同步 | SOAP | 系统集成、跨语言 |
| thrift | — | — | — | 跨语言(Facebook 捐 Apache) |
超时与重试
- 超时设置两处:Provider 端(推荐尽量配,Provider 更懂自己服务)+ Consumer 端(配置则以消费者为准,优先级更高,控制更灵活)。
- 默认调用失败重试 2 次(Failover 下)。
不变量(必须成立的约束)
- 集群容错与负载均衡**都在 Consumer 端(软负载)**执行,不经中心代理。
- 默认组合 Failover + Random;改配置用
cluster/loadbalance属性。 - 一致性 Hash 只保证相同参数落到同一 Provider,不是所有请求均匀。
常见误解
- 以为"容错就是重试" → Failfast/Failsafe/Failback/Broadcast 各有语义,重试只属于 Failover。
- 以为"轮询最均匀" → RoundRobin 有慢机器请求累积缺陷,LeastActive 才是自适应。
- 以为"dubbo 协议万金油" → 它是为"大并发小数据、消费多生产少"设计的,传大包必须换协议。
关联
- 调用链:[概念卡片:Dubbo RPC框架](./概念卡片:Dubbo RPC框架)
- SPI/架构:[概念卡片:Dubbo SPI扩展机制](./概念卡片:Dubbo SPI扩展机制)
- 总览:RPC技术栈总览
- 面试:面试题蒸馏卡:Dubbo