跳到正文
Elaine Blog
返回

手写轻量 RPC 框架:从调用假象到失败语义

网络与 I/O

RPC(远程过程调用)让调用远程服务看起来像调用本地方法,但网络会增加延迟、部分失败、重复执行和版本不一致。框架可以隐藏编码细节,不能消除这些事实。

Table of contents

Open 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 应用。


分享这篇文章:

上一篇
从 Netty 源码理解启动与读写链路
下一篇
Tomcat 容器、连接器与请求链路