RPC(远程过程调用)让调用远程服务看起来像调用本地方法,但网络会增加延迟、部分失败、重复执行和版本不一致。框架可以隐藏编码细节,不能消除这些事实。
Table of contents
运行最小调用链
下载轻量 RPC 样例下载:
mvn -Dtest=NetworkServerLabTest#correlatesAnRpcResponse test
样例为每个请求生成 ID,把 CompletableFuture 放入待完成表;响应到达时用 ID 找到调用方。orTimeout 负责截止,whenComplete 无论成功失败都清理表项。
这个内存版省略了 Socket,目的是先独立验证并发关联和超时清理。
一个可演进协议需要什么
请求至少包含协议版本、消息类型、请求 ID、服务、方法、参数和元数据;响应包含相同请求 ID、结果或结构化错误。帧长度必须有限,未知版本要明确拒绝。
序列化格式影响跨语言和演进能力。JSON 易观察但体积较大;Protobuf 等带模式格式更紧凑,却需要管理字段编号和兼容规则。不要把 Java 类名当成公开协议。
服务发现和负载均衡
服务发现把逻辑服务名映射成可用实例列表。实例上下线、健康检查结果和配置都有传播延迟,所以客户端必须能处理选中实例恰好失效。
负载均衡不是只做随机选择。还要考虑在途请求、实例权重、机房亲和、慢实例隔离和连接复用。客户端缓存的实例列表要有版本与过期策略。
超时、取消、重试
调用链应传播一个绝对截止时间,而不是每经过一层重新获得完整超时。客户端超时后要移除待完成项,并尽力发送取消;服务端收到取消也只能尽力停止, 不能承诺业务从未执行。
自动重试只适合可恢复错误和幂等操作。一次请求的多次尝试共享总截止时间和重试预算,并加入退避抖动。框架应把连接失败、超时、服务端过载和业务错误分开表达。
从实验到可用框架
按顺序增加:真实长度字段编解码、Netty 客户端和服务器、服务注册表、序列化、截止时间、过载保护、指标与追踪。每加一层都先补失败测试:半包、错误长度、 未知服务、响应乱序、连接断开、超时后迟到响应。
生产 RPC 还需要认证、加密、灰度兼容和治理控制面。手写项目的价值是理解边界,不是替代经过安全审查的成熟框架。
下一步
阅读Tomcat 容器、连接器与请求链路,观察另一类 Java 服务器怎样承载 Servlet 应用。