Go 官方 net/rpc 不适合生产级微服务,因缺乏服务发现、负载均衡、超时控制、重试和可观测性支持,仅适用于单机调试或极简场景。

Go 官方 net/rpc 不适合生产级微服务,它缺乏服务发现、负载均衡、超时控制、重试和可观测性支持,仅适用于单机调试或极简场景。
为什么 rpc.Register 必须传入指针类型对象
因为 rpc.Server 内部会通过反射遍历结构体方法,要求接收者是导出的(首字母大写)且必须为指针类型——否则无法在运行时修改其字段或调用方法。若传入值类型如 new(Arith) 实际上传的是 *Arith,而直接写 Arith{} 会导致注册失败,错误信息通常是 "method has wrong number of arguments" 或静默忽略方法。
- 结构体方法签名必须严格满足:
func (t *T) MethodName(args *Args, reply *Reply) error -
Args和Reply类型必须可被encoding/gob序列化(不能含未导出字段、chan、func、unsafe.Pointer) - 注册时若方法名重复(如两个服务都注册了
HelloService),后注册的会覆盖前者,无警告
rpc.ServeConn 和 rpc.Accept 的关键区别
rpc.Accept 是阻塞式监听循环,内部调用 listener.Accept() 并对每个连接启动 goroutine 执行 rpc.ServeConn;而 rpc.ServeConn 是单连接处理函数,只负责解析一次完整的 RPC 请求/响应流。生产中更推荐手动调用 rpc.ServeConn,便于控制连接生命周期、添加中间件(如日志、认证)或复用连接池。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
-
rpc.Accept(l)等价于:for { conn, _ := l.Accept(); go rpc.ServeConn(conn) } - 若连接未显式关闭,
rpc.ServeConn会在读取失败后退出,但不会主动 close 连接,需自行管理 - HTTP 绑定方式(
rpc.HandleHTTP())本质是把 RPC 请求伪装成 HTTP POST,路径固定为/RPC2,不支持 REST 路由或自定义 header
跨语言调用失败的三个硬限制
官方 net/rpc 默认使用 gob 编解码,这导致它天然无法跨语言:Java、Python、Rust 等均无标准 gob 解析器。即使改用 net/rpc/jsonrpc,仍存在协议层兼容问题——它基于 TCP 封帧,而非 HTTP,且不支持 JSON-RPC 2.0 的 batch request、error code 规范。
立即学习“go语言免费学习笔记(深入)”;
-
jsonrpc客户端必须用 Go 的rpc.DialHTTP或rpc.Dial,不能用 curl 或 Postman 直连 - 请求体必须是纯 JSON 对象,字段名需与 Go 结构体导出名完全一致(如
A不能写成a),否则反序列化失败返回空值 - 服务端返回的 error 在 JSON 中表现为
{"error": "xxx"},但客户端需手动检查err != nil,不会自动转成异常抛出
真正要落地微服务,得放弃 net/rpc 原生包,转向 gRPC 或基于 protobuf 的框架——它们解决的不是“能不能调通”,而是“怎么稳定、可观测、可运维地调通”。net/rpc 的设计初衷本就是教学演示,它的简洁恰恰掩盖了分布式系统里最麻烦的部分:连接状态、序列化边界、超时传播和上下文透传。

















