保持 Golang net/rpc 的连接

huangapple go评论70阅读模式
英文:

Keeping connection for Golang net/rpc

问题

根据我理解,在这里阅读net/rpc包的文档<https://pkg.go.dev/net/rpc@go1.17.5>,每当客户端向服务器发起RPC调用时,都会建立一个新的连接。如何实现每个新客户端打开一个新连接并保持连接活动,并且只使用TCP调用RPC方法,而不使用HTTP呢?

英文:

As I understand, reading net/rpc package documentation here
<https://pkg.go.dev/net/rpc@go1.17.5> that every time a client makes an rpc call to the server, a new connection established. How can achieve that each new client opens a new connection, keeps it alive and invokes RPC methods using only TPC, i.e. not using HTTP?

答案1

得分: 3

如果您使用标准库方法创建一个新的客户端:

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

在底层,它将调用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) // 替换为日志消息?
	}
	// 对`conn`进行操作
	go func() {
		server.ServeConn(conn)
		// 服务器已停止为此连接提供服务,您可以将其删除。
	}()
}

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

英文:

If you make a new client with any of the standard library methods:

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

Underneath the hood it will call net.Dial, resulting in a single connection that is associated with the rpc.Client:

conn, err := net.Dial(network, address)

You can see NewClient taking a single connection when it's instantiated here: 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

Any calls to Client.Call on that client will write and read to that underlying connection without spawning a new connection.

So as long as you instantiate your client one time and then make all of your rpc calls to that same client you'll always use a single connection. If that connection ever is severed the client will not longer be usable.

rpc.Client is also threadsafe, so you can safely create it and use it all over the place without having to make new connections .


Answering your comment. If you wanted to run an rpc server and keep track of connections you could do this:

l, e := net.Listen(&quot;tcp&quot;, &quot;:1234&quot;)
if e != nil {
	log.Fatal(&quot;listen error:&quot;, 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.
	}()
}

And then do something with each connection as it came in, and remove it when it's done processing.

huangapple
  • 本文由 发表于 2021年12月13日 05:12:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/70327729.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定