Docker 服务在一段时间后停止通信

Docker services stops communicating after some time

我在 docker 群中共有 6 个容器 运行ning。 Kafka+Zookeeper,MongoDB,A、B、C和接口。接口是来自public的主要访问点——只有这个容器发布端口——5683。接口容器在启动期间连接到A、B和C。我正在使用 docker-compose file + docker stack deploy,每个服务都有一个名称,用作接口的主机。一切都成功启动并且工作正常。一段时间后(20 分钟,1 小时,..)我无法向界面发出请求。接口收到我的请求,但应用程序与服务 A、B、C 或所有这些失去连接。如果我重新启动界面,它能够重新连接到服务 A、B、C。

我首先认为这是应用程序的问题,所以我在每个服务(接口、A、B、C)上公开了 2 个新端口,并与分析器和调试器连接到它们。应用程序 运行 正常运行,没有泄漏,没有阻塞线程,正常工作并等待连接。调试器告诉我,当我向接口发出请求并且接口尝试请求服务 A 时,抛出了对等异常重置的连接。

在调试过程中,我发现了一些有趣的东西。我在服务启动时将调试器连接到接口,并且调试器在一段时间后断开连接。 + 在我向容器 -> 应用程序发出请求之前,我无法重新连接它。问题 - 握手失败。

我发现的另一个有趣的事情是我无法请求这两个接口。所以我使用 wireshark 查看发生了什么并且:SYN - ACK 很好。然后应用post一些数据和接口用FIN,ACK响应。我假设当接口尝试请求服务 A 并且它 FIN 连接时也会发生这种情况。接口的代码库,A,B和C对于netty服务器是相同的。

最后,我认为这不是应用程序的问题。为什么?我尝试将容器而不是服务部署。我 运行 每个容器分别发布了每个容器的端口和服务的端点都设置为本地主机。 (不是覆盖网络)。它正在工作。容器 运行 没有问题。 + 我一开始并没有说 java 应用程序(接口,A、B、C) 运行 当它们作为独立应用程序 运行 时没有问题 - 不是在 docker.

你能帮我看看是什么问题吗?为什么覆盖网络的 docker 正在关闭套接字?

我正在使用最新的 docker。我用的也比较老

终于解决了问题

发生了什么事,再来一次。接口打开与 A、B、C 的永久 TCP 连接。当您尝试 运行 这些服务 A、B、C 作为独立的 java 应用程序时,一切正常。当我们 docker 对它们进行 运行 集群处理时,它只工作了几分钟。奇怪的是,当你从客户端向接口发出请求的那一刻,接口和另一个服务之间的连接被中断了。

经过多次不成功的测试和调试每个容器后,我尝试 运行 每个 docker 容器分别使用映射端口和指定 localhost 作为端点。 (每个容器暴露的端口和接口都连接到本地主机)有趣的事情发生了,它正在工作。当您像这样 运行 容器时,将使用不同的容器网络驱动程序。桥一。如果你 运行 它在 swarm 中,则使用覆盖网络驱动程序。

所以它必须是 docker 网络的东西,而不是应用程序本身。下一步是在几分钟后从每个容器中进行 tcpdump,此时它应该停止工作。很有意思。

  • 客户端 -> 界面(OK,接受请求)
  • 接口->(转发请求,因为它属于A)A
    • 接口 -> A [POST]
    • A -> 接口 [重置]

A 在几分钟没有通信后正在重置打开的 TCP 通信。为什么?

Docker 使用 IP 虚拟服务器并且 IPVS 维护自己的连接 table。 IPVS table 中 CLOSE_WAIT 连接的默认超时为 60 秒。因此,当服务器在 60 秒后发送内容时,IPVS 连接不再可用并且数据包对于新的 TCP 会话看起来无效并获得 RST。在客户端,连接永远保持在 FIN_WAIT2 状态,因为应用程序仍然打开套接字;内核的 fin_wait 计时器仅针对孤立的 TCP 套接字启动。

这就是我读到的以及对它的理解。我不确定我对问题的解释是否正确,但基于这些假设,我在接口和 A、B、C 服务之间实现了乒乓,以防 <60 秒内没有通信。而且,它正在工作。