如何实现无损grpc流调用?

时间:2019-07-16 17:42:01

标签: java streaming grpc grpc-java retry-logic

我在Java中使用grpc-streaming。我有一个持久的开放流,客户端和服务器可以同时进行通信。当我打电话给onNext来发送消息时,grpc在内部缓冲该消息并将异步地将其发送到网络上。现在,如果流在发送数据的过程中丢失,则会调用onError。我不知道什么是正确的做法:

  1. 找出成功发送了哪些消息
  2. 如何重试未发送的邮件

当前,我正在考虑在应用程序层中实现“ ack”机制,其中接收到的每x个项目,接收方都会发送回ack消息。然后,为了执行重试,我需要在发送方缓存项目,并且仅在收到ack时才将其从缓冲区中删除。另外,在接收方,我需要实现一种机制来忽略收到的重复项。

示例: 假设我们每发送100个邮件发送一个ack。我们收到批次3(200-300)的确认,然后在发送项目300-400时收到错误消息。我们再次尝试发送300-400项,但客户已成功接收300-330项,它将再次接收它们。因此,客户需要忽略前30个项目。

可以在应用程序层中实现它。但是,我想知道是否有更好的实践/框架可以解决此问题。

1 个答案:

答案 0 :(得分:0)

经常使用的术语是保证交付,用于描述从一个地方到另一个地方的交付数据而不会造成损失。

您的用例类似于尝试在UDP等尽力而为的传输传输层上提供有保证的传输。通常的方法是确认每个数据包,尽管您可以根据您的建议设计一个方案来进行更高级别的检查。

您通常还希望使用某种形式的滑动窗口,这意味着您不必在发送下一个数据包之前等待上一个ack-这有助于避免延迟。

在此答案中,对UDP的这种方法有很好的概述:https://stackoverflow.com/a/15630015/334402

对于您的情况,您将收到对您的RPC调用的响应,该响应实际上将是确认-使用滑动窗口可以让您在收到上一个请求的确认之前进行下一个调用。

您的重复交付示例也很常见-避免重复计算或感到困惑的一种常见方法是获取数据包编号,然后简单地丢弃所有重复的数据包。