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

Ken*_*Ken 11 c++ client channel stub grpc

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

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

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

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

ppl*_*ins 11

我认为首先我们需要澄清channelstub的定义,根据官方文档

频道

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

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

存根

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

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

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

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

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

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

  1. 的问题报告示例是用 ruby​​ 编写的,但我也可以找到站在对面的python 示例。因此行为可能取决于语言实现

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

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

现在,回到你的问题:

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

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

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

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

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

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

希望这可以帮助!

  • gRPC 鼓励共享渠道。如果任何语言在共享频道时遇到问题,那么这是一个应该修复的错误。 (3认同)
  • @Ken,@Eric Anderson 是 grpc 的贡献者之一。我认为他的回答很有道理,也很权威。我们刚刚在 [gitter/grpc](https://live.staticflickr.com/65535/47970870993_0c9323902a_o.png) 上进行了一次对话,我想这可以让你现在大部分的困惑都清楚了。 (2认同)