我应该共享gRPC存根还是通道

Should I share gRPC Stubs or Channels?

本文关键字:通道 存根 共享 gRPC 我应该      更新时间:2023-10-16

用于创建通道的gRPC C++API返回一个shared_ptr。生成的函数NewStub返回一个unique_ptr。然而,我看到有报告称,有人在尝试创建一个存根类型的多个实例、共享一个通道时遇到问题。他们的解决方案是共享存根。

从文档或API中还不清楚客户端是要创建多个共享通道的存根实例,还是要共享一个存根。请澄清存根、通道和唯一客户端连接之间的概念关系。

潜水更深一点:服务器可以为多个服务提供服务,客户端端点可以使用单个通道将相应的存根类型连接到这些服务中的每一个。为此,很明显,不同的存根类型共享一个通道来与服务器端点进行通信。对于给定的服务,gRPC是否期望每个通道只有一个客户端,或者我是否可以在客户端端点上有多个客户端与单个服务通信?如果允许,如何在客户端端点上为给定的服务实现多个客户端?服务器如何将这些客户端区分为独立客户端?

顺便说一句,这篇SO文章表明Channels和Stubs都是线程安全的。(这篇文章是专门针对Java的,但我认为它会延续到C++)。

我认为首先我们需要根据官方文件澄清通道存根的定义:

通道

gRPC通道提供到指定主机和端口上的gRPC服务器的连接…

结论:通道表示单个TCP连接

存根

在客户端,客户端有一个称为stub的本地对象(对于某些语言,首选术语是client),它实现与服务相同的方法。

结论:存根表示单个客户端

通过阅读许多其他材料,我确信单个通道(tcp连接)可以复用,现在我们有两种选择来实现它:

  1. 一个通道<-->一个存根
    一个存根<-->多路

  2. 一个通道<-->多个存根
    一个存根<-->多路

唯一的区别是是否在存根之间共享通道。我的答案是:是的,你可以,原因是:

  1. 您的人员问题报告示例是用ruby编写的,但我也可以找到相反的python示例。因此行为可能取决于语言实现

  2. 同步cpp客户端示例使用一个存根对象来发出rpc,并且它没有任何流对象与之关联,那么实现多路复用目的的唯一方法就是在存根之间共享一个单一通道对象

结合以上两个原因,我得出结论:在存根之间共享通道在C++中是有效的

现在,回到你的问题:

gRPC是否期望给定服务的每个通道只有一个客户端,或者我是否可以在客户端端点上有多个客户端与单个服务通信?

当然,您可以让多个客户端与一个服务对话。

如果允许,如何在客户端端点上为给定服务实现多个客户端?

您可以只从一个通道或多个通道生成多个存根,考虑到连接开销,前者是更好的选择。

服务器如何将这些客户端区分为独立客户端?

这是由于http2,它可以多路复用,并有自己的规则来实现这一点,grpc需要做的就是遵循这些规则。

希望这能有所帮助!