gRPC client 如何实现 TCP 重连

之前写过一篇 gRPC-go 建立 TCP 连接的过程 博客,主要研究了 client 程序启动后,如何与 server 建立 TCP 连接。 今天,在思考 redis-go 的连接池实现的时候,突然想到: 当 gRPC 的 TCP 连接断开后,能自动重连吗? 如果可以,是如何实现的 ? 首先要注意,这里指的是 TCP 连接,而不是 http2 中的 stream。 我们知道,gRPC 数据的传输使用 http2 的多路复用,也就是在一个 TCP 连接上有多个全双工的 http2 stream,这里的 stream 如果被断开后怎么重连与 http2 的实现有关,不在本文讨论范围。 对于上面第一个问题,使用 gRPC 的经验告诉我是可以自动重连的,不妨再做个简单的测试,client 端代码如下: func main() { conn, _ := grpc.Dial("127.0.0.1:8080", grpc.WithInsecure()) defer conn.Close() cli := protobuf.NewTestClient(conn) req := &protobuf.EchoRequest{ Msg: "hi", } for i := 0; i < 10000; i++ { time....

2022-04-04 · Me

How gRPC-go set up the TCP connection

首先看一个最简单的建立 client server 之间 gRPC 连接的代码,以这个代码为例,分析一下 TCP 是在何时建立的。 Server 端的代码相对来说很容易,一个最简单的 server 代码如下: func main() { lis, _ := net.Listen("tcp", fmt.Sprintf(":%d", 8080)) grpcServer := grpc.NewServer() protobuf.RegisterTestServer(grpcServer, &server{}) grpcServer.Serve(lis) } 在 grpc/server.go 中的 Serve() 函数调用了 lis.Accept() 并阻塞,当 client 端发来 TCP 请求时,Accept() 返回 Conn 结构,并开启 goroutine handleRawConn() 进行后续的处理。 就 TCP 来说,server 端的代码简单易懂,相比之下 client 端则不一样,一个基本的 Client 代码如下: func main() { conn, err := grpc.Dial("localhost:8080", grpc.WithInsecure()) defer conn.Close() cli := protobuf.NewTestClient(conn) } 而要弄清楚 Client 端如何建立 TCP 却不容易,这是因为 grpc client 有 resolve DNS 以及做 load balancer 的功能,因此代码复杂很多。...

2020-10-11 · Me