今天来讲一讲gRPC的多路复用,gRPC 的多路复用是指 一个 gRPC 服务器端可以运行多个 gRPC 服务,也允许多个客户端存根使用同一个 gRPC 客户端连接。

我们继续沿用前面的代码来讲解如何使用多路复用。

多个 gRPC 服务共享同一个服务器端

假如在订单服务中, 为了管理的需求,需要在同一个服务端运行另一个 RPC 服务,这样客户端就能重用同一个连接,这样就可以按需调用相应的服务。 通过相应的服务器端注册函数,可以使多个服务注册在同一个服务器端。

具体代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
func main() {
    initSampleData()
    lis, err := net.Listen("tcp", port)
    if err != nil {
        log.Fatalf("failed to isten: %v", err)
    }
    
    s := grpc.NewServer(grpc.UnaryInterceptor(orderUnaryServerInterceptor))
    ordermgt_pb.RegisterOrderManagementServer(s, &orderMgtServer{})
    user_pb.RegisterUserManagementServer(s, &userMgtServer{})
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

这样就是多个 gRPC 服务共享同一个服务端连接,这样就可以按需调用相应的服务。同理,通过客户端,可以在两个 gRPC 客户端存根间共享相同的 gRPC 客户端连接。

两个 gRPC 客户端存根共享同一个客户端连接

如代码所示,两个 gRPC 服务在同一个 gRPC 服务器端运行,所以可以创建一个 gRPC 连接,并在两个服务创建 gRPC 客户端实例时使用这个连接。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
func main() {
    conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
    if err != nil {
     log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()
    client := pb.NewOrderManagementClient(conn)
    ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
    defer cancel()
    heclien := hwpb.NewGreetingClient(conn)

}

小结

在我们的日常使用中,通常不会出现两个服务间共享同一个服务器端连接的情况。

在微服务架构中,gRPC 多路复用的一个强大的用途是在同一个服务端进程中托管同一个服务的多个版本。这样保证 API 发送 break_channge 时依然能够兼容旧的客户端,