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

时间:2017-04-09 19:33:05

标签: docker netty docker-swarm

我有6个容器在docker swarm中运行。 Kafka + Zookeeper,MongoDB,A,B,C和Interface。接口是public的主要访问点 - 只有这个容器发布端口 - 5683.接口容器在启动时连接到A,B和C.我正在使用docker-compose文件+ docker堆栈部署,每个服务都有一个名称,用作接口的主机。一切都成功开始,工作正常。一段时间后(20分钟,1小时......),我无法提出接口请求。接口接收我的请求但应用程序丢失了与服务A,B,C或所有服务的连接。如果我重新启动接口,它就能够重新连接到服务A,B,C。

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

在调试期间,我发现了有趣的东西。我在服务启动时将调试器附加到接口,并且一段时间后调试器也断开连接。 +我无法重新连接,直到我向容器发出请求 - >应用。 PRoblem - 握手失败。

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

最后,我不认为这是一个应用程序问题。为什么?我试图将容器部署为服务。我分别运行每个容器,发布每个端口并将服务端点设置为localhost。 (不覆盖网络)。它正在发挥作用。容器运行没有问题。 +我一开始没有说,java应用程序(接口,A,B,C)在作为独立应用程序运行时运行没有问题 - 而不是在docker中运行。

你能帮我解决一下这个问题吗?为什么在覆盖网络的情况下docker正在关闭套接字?

我正在使用最新的码头工具。我也用过了。

1 个答案:

答案 0 :(得分:7)

最后,我能够解决问题。

又发生了什么事。接口打开与A,B,C的永久TCP连接。当您尝试将这些服务A,B,C作为独立的Java应用程序运行时,一切正常。当我们将它们对接并在群中运行时,它只工作了几分钟。奇怪的是,当您从客户端向接口发出请求时,Interface和另一个服务之间的连接被中断。

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

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

  • 客户 - >界面(确定,请求接受)
  • 接口 - >(转发请求,因为它属于A)A
    • 界面 - > A [POST]
    • A - >界面[RESET]

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

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

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