07-03-B-RPC与通信面试与生产事故实战
07-03-B-RPC与通信面试与生产事故实战️关键词RPC 面试题 · Dubbo · SPI · 序列化 · HTTP vs RPC · gRPC · 超时重试 · 服务雪崩导读这是《29-A-RPC与通信详解》的配套 B 篇。A 篇讲RPC 原理、Dubbo 架构、序列化协议、HTTP vs RPC 选型本篇讲面试官怎么考、生产上怎么炸、炸了怎么救。RPC 面试喜欢考原理对比RPC 调用链路、Dubbo SPI、序列化选型、HTTP vs RPC生产事故则集中在超时重试风暴、序列化不兼容、连接池耗尽、协议升级翻车。高频题按知识依赖链一问一答连贯展开每题 30 秒电梯版 → 深挖版 → 追问链事故按场景 → 根因 → 预防 → 解决 → 一句话教训五段式复盘。原理细节标注见 A 篇 x.x 节。 目录07-03-B-RPC与通信面试与生产事故实战一、高频面试题精讲连贯问答链链条①RPC 原理四连问链条②序列化与选型三连问链条③治理与可靠性三连问二、生产事故案例集五段式复盘事故一Failover 重试非幂等写操作重复扣款事故二序列化不兼容Provider 升级后 Consumer 全部反序列化失败事故三连接池耗尽RPC 调用全部超时事故四Hessian 换 Protobuf 协议升级Consumer 没同步升级全挂三、事故速查表四、面试答题万能框架五、与 A 篇的知识点映射一、高频面试题精讲连贯问答链链条①RPC 原理四连问Q1什么是 RPC一次 RPC 调用的完整链路** 30 秒电梯版**RPCRemote Procedure Call 远程过程调用——像调本地方法一样调远程服务底层帮你做网络通信见 A 篇第一章。调用链路六步① 动态代理拦截方法调用 → ② 序列化参数对象→字节流→ ③ 网络传输TCP/HTTP→ ④ Provider 反序列化 → ⑤ 反射调用真实方法 → ⑥ 结果序列化返回Consumer 反序列化。一句话总结RPC 动态代理序列化网络传输服务发现——把跨网络调用包装成本地方法调用六步链路。** 深挖版**要点说明动态代理为远程接口生成代理对象——方法调用转网络请求调用方无感知长连接RPC 用长连接连接池——不用每次建连接省握手开销与 HTTP 对比HTTP 每次请求独立HTTP/1.1 keep-alive 缓解RPC 长连接二进制——性能更高** 追问链**Dubbo 架构→ Q2Q2Dubbo 的架构四大角色** 30 秒电梯版**四大角色见 A 篇第二章Provider服务提供者暴露服务注册到 RegistryConsumer服务消费者从 Registry 查 Provider发起 RPC 调用Registry注册中心ZK/Nacos服务注册与发现Monitor监控中心统计调用次数/耗时/成功率。一句话总结Provider 暴露、Consumer 调用、Registry 注册发现、Monitor 监控——Consumer 从 Registry 订阅 Provider 列表负载均衡选一个调用。** 深挖版**要点说明调用流程注册→订阅→推送→负载均衡→调用→上报监控集群容错Failover重试默认/Failfast快速失败/Failsafe安全失败/Failback自动恢复服务治理路由规则/权重/黑白名单/降级——运行时动态调整** 追问链**Dubbo SPI→ Q3Q3Dubbo SPI 和 JDK SPI 的区别** 30 秒电梯版**维度JDK SPIDubbo SPI加载一次性加载所有实现按需加载指定实现配置META-INF/services无 keyMETA-INF/dubbokeyvalue扩展不支持支持 IoC注入 AOPWrapper一句话总结JDK SPI 一次性加载所有实现浪费Dubbo SPI 按需加载keyvalue支持 IoC/AOP——Dubbo 的协议/序列化/负载均衡都是 SPI 扩展点。** 深挖版**要点说明按需加载getExtension(“dubbo”) 只加载 DubboProtocol不加载 http/grpc——不浪费IoC 扩展扩展点可以注入其他扩展点——依赖自动装配AOP 扩展Wrapper 包装扩展点——自动加日志/监控** 追问链**序列化怎么选→ Q5Q4RPC 怎么实现负载均衡和服务发现** 30 秒电梯版**服务发现Provider 注册到 RegistryConsumer 订阅 Registry 获取 Provider 列表——和 Spring Cloud 注册中心同款思想。负载均衡客户端Consumer 拿到 Provider 列表后按策略选一个——轮询/随机/最少活跃/一致性哈希/加权。一句话总结服务发现靠注册中心订阅推送负载均衡靠客户端策略轮询/随机/最少活跃——RPC 是客户端负载均衡。** 深挖版**要点说明最少活跃选当前活跃调用数最少的 Provider——慢的 Provider 少分配一致性哈希相同参数哈希到同一 Provider——缓存友好与 Spring Cloud 对比Dubbo 和 Spring Cloud 都是客户端负载均衡——思想相同实现不同链条②序列化与选型三连问Q5序列化协议怎么选JSON/Hessian/Protobuf/Kryo 的区别** 30 秒电梯版**维度JSONHessianProtobufKryo格式文本二进制二进制二进制可读性好差差差体积/速度大/慢中/快最小/最快小/极快跨语言好中好差成本低低高.proto代码生成低选型REST API/调试用 JSONDubbo 默认 Hessian高性能/跨语言用 ProtobufJava 内部极致用 Kryo。一句话总结JSON 可读但慢Protobuf 快但要 .proto 定义Hessian 是 Dubbo 平衡选择——按可读性 vs 性能 vs 跨语言三角选型。** 深挖版**要点说明Protobuf 快的原因二进制字段编号不存字段名varint 编码——体积比 JSON 小 3~10 倍Protobuf 的代价.proto 定义代码生成版本兼容——开发成本高序列化不兼容类结构变更加字段/改类型导致反序列化失败——版本兼容是序列化的坑** 追问链**HTTP vs RPC→ Q6Q6HTTP 和 RPC 怎么选** 30 秒电梯版**维度HTTPRESTRPCDubbo/gRPC性能慢文本头部开销快二进制长连接跨语言/调试好中/差服务治理弱强内置适用对外 API/跨团队内部微服务/高性能选型口诀对外 API 用 HTTP通用易调试内部微服务用 RPC高性能服务治理——Java 内部选 Dubbo多语言选 gRPC。一句话总结HTTP 和 RPC 不是谁更好是谁更匹配场景——对外要通用选 HTTP内部要性能选 RPC。** 深挖版**要点说明混合架构网关对外 HTTP内部微服务 RPC——常见组合gRPC 跨语言HTTP/2Protobuf——多语言微服务选 gRPC性能差距RPC 比 HTTP 快 3~10 倍二进制长连接多路复用——高 QPS 内部调用差距明显** 追问链**gRPC 为什么快→ Q7Q7gRPC 为什么快** 30 秒电梯版**三大快因见 A 篇第六章HTTP/2 多路复用一个 TCP 连接并行多个请求——不用为每个请求建连接省握手开销Protobuf 序列化二进制字段编号——体积比 JSON 小 3~10 倍速度快 5~20 倍头部压缩零拷贝HTTP/2 HPACK 头部压缩二进制帧直接传输。一句话总结HTTP/2 多路复用省连接、Protobuf 省体积、头部压缩省带宽——三个优化叠出 gRPC 的高性能。** 深挖版**要点说明多路复用一个连接上多个 stream 并行——队头阻塞在 stream 级解决gRPC vs DubbogRPC 跨语言强Google 生态Dubbo 服务治理强Java 生态.proto 驱动IDL 定义接口消息——代码生成跨语言一致链条③治理与可靠性三连问Q8RPC 调用失败怎么办集群容错策略** 30 秒电梯版**Dubbo 集群容错策略策略行为适用Failover失败自动重试其他 Provider默认读操作/幂等写Failfast失败立即报错不重试非幂等写操作Failsafe失败忽略返回空日志/监控等不重要调用Failback失败记录定时重发消息通知一句话总结读操作 Failover 重试非幂等写 Failfast 快速失败不重要调用 Failsafe 忽略——重试只给幂等操作。** 深挖版**要点说明重试的坑非幂等写操作重试 重复执行——写操作要幂等或用 Failfast重试风暴下游慢重试请求放大——重试次数要限制超时配合降级失败率超阈值降级返回兜底——和 Spring Cloud 熔断降级同款** 追问链**RPC 超时怎么设→ Q9Q9RPC 超时怎么设置超时和重试怎么配合** 30 秒电梯版**超时设置原则超时 上游超时调用链超时逐级递减——网关 服务 A 服务 B防止上游等下游按下游 RT 设置超时 下游 P99 RT × 2~3 倍——太短误杀太长拖垮超时重试配合总耗时 超时 × (重试次数1)——总耗时要 上游超时。一句话总结超时逐级递减、按下游 P99 设置、超时×重试次数 上游超时——三者配合防雪崩。** 深挖版**要点说明超时太短误杀正常慢调用——重试放大请求超时太长线程阻塞等待——线程池耗尽动态超时按下游 RT 动态调整超时——自适应** 追问链**RPC 雪崩怎么防→ Q10Q10RPC 调用链雪崩怎么防** 30 秒电梯版**雪崩下游慢/挂 → 调用方线程阻塞 → 线程池耗尽 → 调用方挂 → 上游挂——故障沿调用链蔓延。防雪崩四件套和 Spring Cloud 同款见 28-B Q10超时RPC 调用设超时——不让线程无限等待熔断失败率超阈值熔断——切断对故障下游的调用降级熔断后返回兜底——核心可用非核心降级隔离线程池/信号量隔离——一个下游故障不拖垮其他调用。一句话总结超时防等待、熔断防调用、降级保核心、隔离防蔓延——RPC 和 HTTP 微服务的防雪崩四件套相同。** 深挖版**要点说明线程池隔离每个下游独立线程池——舱壁模式限流Provider 端限流——保护自身不被打爆与 MQ 削峰异步调用用 MQ 削峰——同步 RPC 改异步 MQ二、生产事故案例集五段式复盘事故一Failover 重试非幂等写操作重复扣款** 事故场景**支付服务用 Dubbo 调用扣款接口集群容错策略用默认Failover重试 2 次。某次扣款接口超时实际执行成功但响应慢Failover 重试又调了 2 次——扣款接口非幂等同一笔订单扣了 3 次款用户投诉资损。** 根因分析**Failover 重试非幂等写操作Q8Failover 失败自动重试——但扣款是非幂等写操作重试 重复扣款。超时≠失败实际执行成功但响应慢重试导致重复执行。读操作重试安全非幂等写操作重试 重复执行。️ 预防方案非幂等写用 Failfast扣款/下单等非幂等写操作——失败立即报错不重试写操作幂等化唯一键去重订单号操作类型——重试也不重复执行超时重试配合总耗时 超时 × (重试1) 上游超时——防重试风暴对账兜底支付对账——重复扣款靠对账发现退款。** 事故解决**止血手动退款 2 笔重复扣款根治扣款接口改 Failfast幂等化订单号唯一键全仓扫描非幂等写操作Failover 配置6 处支付对账上线验证注入超时Failfast 不重试幂等拦截重复零重复扣款。** 一句话教训**Failover 重试非幂等写操作 重复执行——超时≠失败重试≠安全非幂等写用 Failfast写操作必须幂等化。事故二序列化不兼容Provider 升级后 Consumer 全部反序列化失败** 事故场景**订单服务Provider升级给 Order 对象加了一个字段couponId重新发布。Consumer 端用户服务/积分服务还是旧版本没有 couponId 字段——Hessian 反序列化失败所有调用订单服务的 Consumer 报错订单详情页/积分发放全部不可用。** 根因分析**序列化不兼容Q5 深挖版Provider 升级加了字段Consumer 旧版本类结构不匹配——Hessian 反序列化时字段对不上抛异常。RPC 的序列化要求Consumer 和 Provider 的类结构兼容——加字段/改类型/删字段都可能不兼容。️ 预防方案序列化版本兼容加字段用默认值兼容Protobuf 天然兼容Hessian/JSON 要注意——只加不删不改类型灰度发布Provider 先灰度 1 个实例——Consumer 报错立即发现接口契约管理IDL/接口版本管理——Consumer 和 Provider 接口版本对齐Protobuf 优先Protobuf 字段编号默认值——向后兼容最好Consumer 先升级先升级 Consumer兼容新旧字段再升级 Provider——顺序不能反。** 事故解决**止血Provider 回滚旧版本根治接口契约管理.proto/接口版本发布顺序规范Consumer 先升级Protobuf 替换 Hessian兼容性好验证模拟加字段升级Protobuf 向后兼容Consumer 不报错。** 一句话教训**Provider 加字段Consumer 旧版本 反序列化失败——RPC 序列化要求类结构兼容只加不删不改类型Consumer 先升级Protobuf 兼容性最好。事故三连接池耗尽RPC 调用全部超时** 事故场景**大促期间订单服务调用库存服务的 RPC 连接池默认 100 连接耗尽——新请求拿不到连接排队等待全部超时。排查发现库存服务 RT 从 10ms 涨到 2s慢查询每个请求占用连接 2s100 连接只能支撑 50 QPS大促 QPS 500连接池瞬间耗尽。** 根因分析**连接池耗尽Q9连接池大小固定100下游 RT 变长2s→ 每个连接占用时间变长 →连接池吞吐量 连接数 / RT 100/2s 50 QPS远低于大促 QPS 500。连接池耗尽 → 新请求排队 → 超时 → 雪崩。️ 预防方案连接池大小按 QPS×RT 估算连接数 QPS × RT × 安全系数——RT 变长要扩连接池超时设置RPC 超时 连接等待超时——拿不到连接快速失败不排队下游慢查询治理库存服务慢查询优化——RT 恢复连接池吞吐恢复熔断降级下游慢触发熔断——不占连接走降级连接池监控活跃连接数/等待队列打点——连接池接近耗尽告警。** 事故解决**止血连接池扩到 500库存服务慢查询优化RT 恢复 10ms根治连接池大小按 QPS×RT 动态估算RPC 超时连接等待超时配置连接池监控告警验证压测 500 QPS下游 RT 2s连接池 500 支撑无排队超时。** 一句话教训**连接池吞吐 连接数 / RT——下游 RT 变长连接池吞吐暴跌连接池按 QPS×RT 估算下游慢要扩池熔断。事故四Hessian 换 Protobuf 协议升级Consumer 没同步升级全挂** 事故场景**订单服务Provider把序列化协议从 Hessian 换成 Protobuf“性能优化”直接全量发布。Consumer 端还是 Hessian 协议——协议不匹配Consumer 收到的 Protobuf 字节流用 Hessian 反序列化全部失败所有调用订单服务的 Consumer 报错服务不可用 20 分钟。** 根因分析**协议升级没同步Q5/Q6Provider 换 ProtobufConsumer 还是 Hessian——序列化协议不匹配反序列化失败。RPC 协议升级要求Consumer 和 Provider 协议一致——单方面升级 通信失败。️ 预防方案协议升级双端同步Consumer 先升级支持 HessianProtobuf 双协议→ Provider 再切 Protobuf——Consumer 兼容新旧协议灰度发布Provider 先灰度 1 个实例切 Protobuf——Consumer 报错立即发现协议协商Dubbo 支持多协议暴露——Provider 同时暴露 HessianProtobufConsumer 按需选变更评审协议/序列化变更要评审双端确认——单方面变更禁止。** 事故解决**止血Provider 回滚 Hessian 协议根治Consumer 升级支持双协议Provider 灰度切 Protobuf协议协商配置变更评审规范验证灰度切 ProtobufConsumer 双协议兼容零报错性能提升 40%。** 一句话教训**协议升级单方面发布 Consumer 全挂——RPC 协议要求双端一致Consumer 先升级兼容双协议Provider 再灰度切换。三、事故速查表现象可能根因快速定位根治方案重复扣款/下单Failover 重试非幂等写容错策略调用日志非幂等写 Failfast幂等化反序列化失败类结构不兼容Provider/Consumer 版本对比只加不删Consumer 先升级Protobuf连接池耗尽下游 RT 变长连接池活跃数下游 RT扩连接池超时熔断协议升级全挂协议不匹配Provider/Consumer 协议对比双协议兼容灰度切换RPC 超时雪崩超时太长无熔断调用链 RT线程池超时递减熔断降级隔离重试风暴下游慢重试放大重试次数下游 QPS限制重试超时配合服务发现失败注册中心故障注册中心状态客户端缓存注册中心高可用四、面试答题万能框架被问 RPC① 先给骨架 RPC动态代理序列化网络服务发现 30 秒讲清调用链路六步。② 按追问深挖 架构线:Dubbo 四角色 / SPI 按需加载序列化线:JSON /Hessian / Protobuf /Kryo 三角 选型线:对外 HTTP 内部 RPC / JavaDubbo 多语言 gRPC 治理线:Failover / Failfast / 超时递减 /防雪崩四件套。③ 落到生产视角 非幂等写 Failfast序列化兼容 连接池按 QPS×RT协议升级双端同步。④ 用事故收尾 Failover 重复扣款 / 序列化不兼容 / 连接池耗尽有画面感的案例胜过背书。加分技巧谈 RPC 原理主动讲六步链路代理拦截→序列化→网络→反序列化→反射调用→结果返回——完整链路谈 SPI 主动带JDK SPI 一次性加载浪费Dubbo SPI 按需加载IoC/AOP——对比理解谈序列化主动说Protobuf 快因为二进制字段编号varint代价是 .proto 定义版本兼容——原理级理解谈容错主动讲Failover 只给幂等读操作非幂等写用 Failfast——重试非幂等写重复执行——踩坑意识被问遇到过什么 RPC 问题用事故一Failover 重复扣款——超时≠失败重试≠安全的教训最有共鸣。五、与 A 篇的知识点映射本篇题目/事故A 篇《29-A-RPC与通信详解》对应章节Q1 RPC 原理/链路一章Q2 Dubbo 架构二章Q3 Dubbo SPI三章Q4 负载均衡/服务发现二章Q5 序列化选型四章Q6 HTTP vs RPC五章Q7 gRPC 快因六章Q8 集群容错2.3Q9 超时设置五章延伸Q10 防雪崩五章延伸事故一 Failover 重复扣款2.3事故二 序列化不兼容四章事故三 连接池耗尽五章延伸事故四 协议升级四章/六章结语RPC 面试题的尽头是透明意识——RPC 把网络通信的复杂性藏起来但复杂性不会消失只会转移序列化要兼容、超时重试要配合、连接池要估算、协议升级要同步生产事故的尽头是双端意识——RPC 是双端通信Consumer 和 Provider 的类结构/协议/版本必须对齐任何单方面变更都是一次事故的伏笔。配套阅读上一篇《07-02-A-SpringCloud全家桶详解.md》A 篇《07-03-A-RPC与通信详解.md》下一篇《07-04-A-分布式理论与实践详解.md》如果这篇文章对你有帮助欢迎点赞、收藏、关注