在grpc中有多个一元rpc调用与长期运行的双向流?

时间:2019-06-26 06:57:13

标签: stream grpc grpc-java

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

2 个答案:

答案 0 :(得分:2)

  

问题是客户端流无法确保应用程序级别的可靠传递(即,如果流在两者之间关闭,那么服务器实际处理了发送的消息数量),而我负担不起

这意味着您需要响应。即使响应只是一个确认,从gRPC的角度来看,它仍然是响应。

通常的方法应该是“使用一元”,除非可以通过流传输解决足够大的问题以克服其复杂性成本。我讨论了此at 2018 CloudNativeCon NA(该视频有幻灯片和YouTube的链接)。

例如,如果您有多个后端,则每个一元RPC可能会发送到不同的后端。这可能会导致这些后端进行自身同步的高开销。流式RPC在开始时选择一个后端,然后继续使用相同的后端。因此,流传输可能会减少后端同步的频率,并在服务实现中实现更高的性能。但是,流式传输会在发生错误时增加复杂性,在这种情况下,它将导致RPC的寿命延长,从而使负载平衡更加复杂。因此,您需要权衡从流式传输/长寿命RPC所增加的复杂性是否为您的应用程序提供了足够大的好处。

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

答案 1 :(得分:1)

流确保消息按照发送的顺序进行传递,这意味着如果有并发消息,就会出现某种瓶颈。< /p>

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

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

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

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

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