【问题标题】:how to implement retry strategy for outbound message over TCP如何通过 TCP 实现出站消息的重试策略
【发布时间】:2017-08-03 18:19:54
【问题描述】:

我有一个使用 Java 通过 TCP 套接字向外部系统发送消息的系统。如果我们想尽最大努力确保接收到发送的消息,是否需要执行重试逻辑以防在发送方法中捕获到网络故障?

在我看来,没有必要重试,因为它已经由 TCP 在后台处理。这个论点有效吗?

谢谢!

【问题讨论】:

  • TCP 确实为您处理了这个问题。一旦你发送数据并且它已经被正确地提供给底层内核,它就无法控制了。如果收到发送错误,则必须断开套接字并连接新的套接字才能再次交换数据。
  • 谢谢雷米!我的问题更多的是在这里重试是否有意义。既然 TCP 已经为我做了重试,我还需要在我的业务逻辑中做重试吗?如果是,应该使用什么重试策略?
  • 您不能在 TCP 中实现自己的重试(仅在 UDP 中)。一旦套接字出错,就是这样。套接字处于错误/未知状态,您所能做的就是断开连接并创建一个新连接。
  • 您知道接收应用程序是否收到您发送的消息的唯一方法是确认每条消息。即,接收应用程序必须发回它已收到的消息。这通常很麻烦,这会导致在消息中引入序列号,并且接收者的任务是跟踪它收到的消息并在丢失任何消息时要求重新发送。如果您对接收器没有那种级别的控制,那么您应该捕获错误并重新发送,但这就是您所能做的,正如 Vovanrock2002 在下面解释的那样。

标签: java sockets tcp


【解决方案1】:

没那么简单。

了解 TCP 是一种传输协议很重要。其目的是在机器之间而不是应用程序之间建立可靠的数据流。成功send 并不代表消息已经送达,它意味着你的内核已经将消息排入队列,很快就会发送出去。当主机收到消息并确认时,这并不意味着您的应用程序已经调用或将调用recv 并实际获取数据。

因此,您当然可以依靠套接字错误来检测断开的连接。但是,当连接中断时,您的应用程序将无法仅根据您可以从 TCP 获取的信息来确定已交付的内容和未交付的内容。

因此,您为程序开发的应用程序级协议需要它自己的机制来跟踪应用程序之间成功交付的内容。重新连接和重试机制将成为其中的一部分。

示例

  1. Alice 通过 TCP 向 Bob 发送包含一些关于她的状态更新的数据包。在某个时间点,爱丽丝要发送三个更新。 Alice 的send 呼叫成功。

  2. 第一次更新是由 Bob recved。他的机器收到了第二次更新,但在 Bob 第二次调用recv 之前机器突然重启。

  3. 第三次更新被 Bob 办公室中的某个安全中间设备丢弃。

  4. Alice 然后想再发送一个更新。连接已经处于错误状态,所以send 失败。

此时,Alice 发送了三个更新,但 Bob 只收到了一个。当 Bob 的机器重新上线并建立新的连接时,Alice 和 Bob 需要在继续进行之前同步他们的状态。他们需要同步,因为 Alice 实际上并不知道 Bob 能够处理多少更新。仅基于 TCP,她可能只能对 Bob 的机器收到多少更新做出有根据的猜测。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 1970-01-01
    • 2020-02-13
    • 2019-05-06
    • 2014-10-11
    相关资源
    最近更新 更多