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

Should I share gRPC Stubs or Channels?

用于创建通道的 gRPC C++ API returns shared_ptr。生成函数NewStubreturnsaunique_ptr。但是我已经看到 reports of people having issues 试图创建一个存根类型的多个实例,共享一个通道。他们的解决方案是共享存根。

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

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

顺便说一句, 表示 Channels 和 Stubs 都是线程安全的。 (post 专门用于 Java,但我假设它会延续到 C++。

我认为首先我们需要根据 official documents 澄清 channelstub 的定义 :

频道 :

A gRPC channel provides a connection to a gRPC server on a specified host and port...

结论:一个通道代表一个 TCP 连接。

存根 :

On the client side, the client has a local object known as stub (for some languages, the preferred term is client) that implements the same methods as the service.

结论:一个存根代表一个客户端。

看了很多其他资料,我确定单通道(tcp连接)可以复用,现在我们有两个方案来实现它:

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

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

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

  1. 你的reports of people having issues example is written in ruby, but I can also find python examples站在对面。所以行为可能取决于语言实现

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

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

现在,回到你的问题:

Does gRPC expect only one client per channel for a given service or can I have multiple clients on the client endpoint talking to a single service?

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

If allowed, how do I achieve multiple clients for a given service on a client endpoint?

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

How does the server distinguish these as independent clients?

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

希望对您有所帮助!