悠悠楠杉
网站页面
正文:
在分布式系统开发中,远程过程调用(RPC)是实现服务间通信的核心技术之一。Golang 标准库中的 net/rpc 包提供了简洁的 RPC 实现,支持基于 HTTP 和原生 TCP 的两种通信协议。本文将对比这两种方式的特性,并结合实际场景给出选型建议。
HTTP RPC 基于应用层协议,天然支持跨语言交互和防火墙穿透,适合对外暴露服务。而 原生 TCP RPC 直接传输二进制数据,减少了协议解析开销,性能更高,但通常用于内网环境。
go
// 服务端
func main() {
rpc.Register(new(Arith))
rpc.HandleHTTP()
http.ListenAndServe(":8080", nil)
}
// 客户端
func main() {
client, err := rpc.DialHTTP("tcp", "localhost:8080")
if err != nil {
log.Fatal("dialing:", err)
}
// 调用远程方法
err = client.Call("Arith.Multiply", args, &reply)
}
go
// 服务端
func main() {
rpc.Register(new(Arith))
listener, _ := net.Listen("tcp", ":8080")
for {
conn, _ := listener.Accept()
go rpc.ServeConn(conn)
}
}
// 客户端
func main() {
client, err := rpc.Dial("tcp", "localhost:8080")
if err != nil {
log.Fatal("dialing:", err)
}
// 调用远程方法
err = client.Call("Arith.Multiply", args, &reply)
}
对于既需对外暴露又需内部高性能调用的服务,可同时监听 HTTP 和 TCP 端口:
go
func main() {
rpc.Register(new(Service))
// 对外 HTTP
go http.ListenAndServe(":8080", nil)
// 对内 TCP
listener, _ := net.Listen("tcp", ":8081")
for {
conn, _ := listener.Accept()
go rpc.ServeConn(conn)
}
}
TCP 长连接需注意资源释放,推荐使用 sync.Pool 复用客户端连接:
go
var clientPool = sync.Pool{
New: func() interface{} {
client, err := rpc.Dial("tcp", "backend:8080")
if err != nil { panic(err) }
return client
},
}
func GetClient() *rpc.Client {
return clientPool.Get().(*rpc.Client)
}
func PutClient(client *rpc.Client) {
clientPool.Put(client)
}
Golang 的 net/rpc 为开发者提供了灵活的通信方案。HTTP 协议适合开放性场景,而 TCP 协议更擅长性能敏感的内部服务调用。实际项目中,可结合业务需求采用混合部署或协议转换网关(如 gRPC-Web)来平衡性能与通用性。