grpc 中的多个一元 rpc 调用与 long-运行 双向流?

Multiple unary rpc calls vs long-running bidirectional streaming in grpc?

我有一个用例,其中许多客户端需要不断向服务器发送大量指标(几乎是永久性的)。服务器需要存储这些事件,并在以后处理它们。我不希望服务器对这些事件做出任何类型的响应。
我正在考虑为此使用 grpc。最初,我认为客户端流式传输可以做到 (like how envoy does),但问题是客户端流式传输无法确保应用程序级别的可靠传输(即,如果流式传输在两者之间关闭,则实际发送了多少消息由服务器处理),我负担不起。
我的思考过程是,我应该使用 bidi 流式传输,在服务器流中使用 acks,或者使用多个一元 rpc 调用(可能在重复字段中对事件进行一些批处理以提高性能)。
哪个更好?

the issue is that client side streaming cannot ensure reliable delivery at application level (i.e. if the stream closed in between, how many messages that were sent were actually processed by the server) and I can't afford this

这意味着您需要回复。哪怕只是一个确认的回应,从gRPC的角度来看也是一个回应。

一般方法应该是 "use unary,",除非足够大的问题可以通过流式处理来解决,以克服它们的复杂性成本。我讨论了这个 at 2018 CloudNativeCon NA(幻灯片和 YouTube 上有 link 视频)。

例如,如果您有多个后端,那么每个一元 RPC 可能会发送到不同的后端。这可能会导致那些不同的后端同步它们自己的开销很高。流式 RPC 在开始时选择一个后端并继续使用相同的后端。因此,流式传输可能会降低后端同步的频率,并在服务实施中实现更高的性能。但是当发生错误时,流式处理会增加复杂性,在这种情况下,它会导致 RPC 变成 long-lived,这对负载平衡来说更复杂。因此,您需要权衡 streaming/long-lived RPC 增加的复杂性是否为您的应用程序带来足够大的好处。

我们通常不建议使用流式 RPC 来获得更高的 gRPC 性能。的确,在流上发送消息比新的一元 RPC 更快,但改进是固定的并且具有更高的复杂性。相反,我们建议使用流式 RPC,因为它可以提供更高的 application(您的代码)性能或更低的 application 复杂性。

流确保消息按发送顺序传送,这意味着如果有并发消息,就会出现某种瓶颈。

Google 的 gRPC 团队建议不要为了性能而使用流而不是一元,但是尽管如此,有人认为从理论上讲,流应该具有更低的开销。但这似乎不是真的。

对于较少数量的并发请求,两者的延迟似乎相当。 但是,对于更高的负载,一元调用的性能要高得多。

没有明显的理由我们应该更喜欢流而不是一元,因为使用流会带来额外的问题,比如

  • 当我们有并发请求时延迟很低
  • 应用程序级别的复杂实现
  • 缺乏负载平衡:客户端将连接到一台服务器并忽略任何新服务器
  • 对网络中断的恢复能力差(即使是 TCP 连接中的小中断也会导致连接失败)

这里有一些基准:https://nshnt.medium.com/using-grpc-streams-for-unary-calls-cd64a1638c8a