Go原生net/rpc功能受限,需定制化改造以支持多语言互通、上下文传递、中间件、自定义协议等;推荐替换为gRPC或HTTP框架,或通过自定义Codec/Conn/Client实现扩展。
Go 语言原生的 net/rpc 包提供了基于 HTTP 或 TCP 的简单 RPC 框架,但默认只支持 Gob 编码、要求方法签名严格匹配、不支持上下文传递、无内置超时与重试,也难以扩展中间件或适配自定义协议。若需满足特定通信需求(如兼容旧系统、对接非 Go 服务、要求 JSON-RPC 兼容、添加鉴权头、支持双向流、或使用 Protobuf 序列化),必须进行定制化改造。
原生 RPC 默认用 Gob,但 Gob 不跨语言。要实现多语言互通,需替换编码器。
jsonrpc 包替代标准 rpc.Server:导入 "net/rpc/jsonrpc",服务端监听时用 jsonrpc.ServeConn;客户端连接后用 jsonrpc.NewClient。net/rpc,改用 gRPC(底层即基于 HTTP/2 + Protobuf),或手动封装:定义 .proto 文件 → 生成 Go 代码 → 在 handler 中解析请求体为 proto.Message → 调用业务逻辑 → 序列化响应返回。rpc.ServerCodec 接口(ReadRequestHeader/ReadRequestBody/WriteResponse 等),再通过 rpc.ServeCodec 启动服务。标准 net/rpc 方法无法接收 context.Context,也不支持拦截请求。可通过包装 handler 实现增强。
server.ServeConn 前,用自定义 net.Conn 包装器读取前置元数据(如 token、trace-id),存入 context.WithValue,再透传至业务方法(需修改方法签名并配合反射调用)。net/rpc,改用轻量 HTTP 框架(如 gin 或 chi)暴露 RPC 风格接口:POST /rpc,请求体为 {"method":"User.Get","params":[123]},统一做日志、鉴权、限流、超时控制,再分发到对应函数。func(*Args, *Reply) error 改为闭包,内部注入 context 并调用实际逻辑。当需要与嵌入式设备、IoT 网关等低开销场景通信时,可能要求精简报文、固定长度头、或二进制帧协议。
net.Conn,在 Read 中按协议解析帧(如 4 字节长度头 + JSON body),在 Write 中先写长度再写内容。rpc.ServerCodec:在 ReadRequestHeader 中解析帧头获取 method 名和序列号;ReadRequestBody 解析后续 payload;WriteResponse 按同样格式打包返回。conn.Read 直到收满指定字节数,不可假设单次读完。原生 rpc.Client 不支持超时,Call 是阻塞同步调用,且无重试机制。
contex
t.WithTimeout 控制调用时限:启动 goroutine 执行 client.Call,主协程 select 等待结果或超时通道。io.EOF、net.OpError 等临时错误,配合指数退避。rpc.Client 连接——注意复用连接避免频繁建链,建议用连接池管理。不复杂但容易忽略:所有自定义都要确保服务端与客户端使用完全一致的编解码规则、错误约定和超时策略。建议将协议规范文档化,并用一组端到端测试验证边界情况(如大 payload、空参数、非法 method 名)。