为 Golang 保持连接 net/rpc

Keeping connection for Golang net/rpc

据我所知,阅读 net/rpc 包文档在这里 https://pkg.go.dev/net/rpc@go1.17.5 每次客户端对服务器进行 rpc 调用时,都会建立一个新连接。如何实现每个新客户端打开一个新连接,使其保持活动状态并仅使用 TPC 调用 RPC 方法,即不使用 HTTP?

如果您使用任何标准库方法创建新客户端:

client, err := rpc.DialHTTP("tcp", serverAddress + ":1234")
if err != nil {
    log.Fatal("dialing:", err)
}

在引擎盖下它将 call net.Dial,导致与 rpc.Client:

关联的单个连接
conn, err := net.Dial(network, address)

您可以看到 NewClient 在此处实例化时采用单个连接:https://cs.opensource.google/go/go/+/refs/tags/go1.17.5:src/net/rpc/client.go;l=193-197;drc=refs%2Ftags%2Fgo1.17.5;bpv=1;bpt=1

在该客户端上对 Client.Call 的任何调用都将写入和读取该底层连接,而不会产生新连接。

因此,只要您实例化您的客户端一次,然后对同一个客户端进行所有 rpc 调用,您将始终使用单个连接。如果该连接被切断,客户端将不再可用。

rpc.Client 也是线程安全的,因此您可以安全地创建它并在所有地方使用它而无需建立新连接。


正在回复您的评论。如果你想 运行 一个 rpc 服务器并跟踪连接,你可以这样做:

l, e := net.Listen("tcp", ":1234")
if e != nil {
    log.Fatal("listen error:", e)
}
server := rpc.NewServer()
for {
    conn, err := l.Accept()
    if err != nil {
        panic(err) // replace with log message?
    }
    // Do something with `conn`
    go func() {
        server.ServeConn(conn)
        // The server has stopped serving this connection, you can remove it.
    }()
}

然后在每个连接进入时对其进行处理,并在处理完成后将其删除。