(网络套接字)字节在发送队列中停留15分钟;为什么?

时间:2009-04-02 09:44:32

标签: java networking routing firewall

我有一个在Windows上运行的Java程序(Citrix机器),它向Linux上的Java应用程序服务器发送请求;这个调度机制都是自定义的。

Windows Java程序(让我们称之为W)打开一个侦听套接字到操作系统给出的端口,比如1234接收结果。然后它在服务器上调用“业务请求”的“调度”服务。此服务拆分请求并将其发送到其他服务器(让我们称之为S1 ... Sn),并同步将作业数返回给客户端。

在我的测试中,有13个作业,分派到多个服务器,在2秒内,所有服务器都已完成处理作业并尝试将结果发送回W的套接字。

我可以在日志中看到W收到9个工作(这个数字因测试而异)。所以,我试着寻找剩下的4个工作。如果我在这个Windows框中执行netstat,我会看到4个套接字已打开:

TCP    W:4373       S5:48197  ESTABLISHED
TCP    W:4373       S5:48198  ESTABLISHED
TCP    W:4373       S6:57642  ESTABLISHED
TCP    W:4373       S7:48295  ESTABLISHED

如果我进行W的线程转储,我会看到4个线程试图从这些套接字读取,并且显然卡在java.net.SocketInputStream.socketRead0(Native Method)中。

如果我继续执行每个S框并执行netstat,我会看到一些字节仍在发送队列中。此字节数不会移动15分钟。 (以下是不同机器上netstat的聚合):

Proto Recv-Q Send-Q Local Address               Foreign Addr   State
tcp        0   6385 S1:48197                          W:4373   ESTABLISHED
tcp        0   6005 S1:48198                          W:4373   ESTABLISHED
tcp        0   6868 S6:57642                          W:4373   ESTABLISHED
tcp        0   6787 S7:48295                          W:4373   ESTABLISHED

如果我对服务器执行线程转储,我会看到线程也被卡住了 java.net.SocketInputStream.socketRead0(Native Method)。我希望写一个,但也许他们在等待一个ACK? (这里不确定;它会用Java显示吗?不应该直接用TCP协议处理吗?)

现在,非常奇怪的是:15分钟后(总是15分钟),结果收到,套接字关闭,一切都正常。

以前一直都这样。 S服务器已移至其他数据中心,因此WS不再位于同一数据中心。此外,S位于防火墙后面。所有端口都应在SW之间授权(我被告知)。神秘的确是15分钟的延迟。我认为这可能是对DDOS的一些保护吗?

我不是网络专家,所以我求助,但没有人可以帮助我。我花了30分钟与一个人用Wireshark(以前的Ethereal)捕获数据包,但出于“安全原因”,我无法查看结果。他必须分析这个并回复我。我问了防火墙日志;同样的故事。

我不是这些盒子的根或管理员,现在我不知道该做什么......我不期待你们的解决方案,但是关于如何进步的一些想法会很棒!

4 个答案:

答案 0 :(得分:3)

如果它在您的本地网络中运行正常,那么我不认为这是一个编程问题(重新flush()评论)。

两台机器之间的网络连接是否正常?您可以通过(比如)FTP传输类似数量的数据,没有任何问题。您是否可以通过将客户端/服务器脚本组合在一起来发送适当大小的数据块来复制此问题。即W和S之间的网络连接是否良好?

另一个问题。你现在有一个防火墙。这可能是以前没有的瓶颈吗? (不知道如何解释一致的15米延迟)。

最后的问题。您的TCP配置参数设置为什么(在W和S上 - 我正在考虑操作系统级参数)。那里有什么可以暗示或导致15米的数字。

不确定是否有任何帮助。

答案 1 :(得分:1)

右。如果您正在使用BufferedOutputStream,则需要调用flush(),除非您达到最大缓冲区大小。

答案 2 :(得分:1)

除了尝试Brian说,您还可以查看以下内容

1)在任何一台服务器上运行tcpdump,并查看从启动作业到延迟之后,当所有处理完成时的消息流序列。这将告诉你哪一方导致延迟(W或S)。检查是否有任何重传,错过的确认等。

2)W和S之间是否存在某种碎片?

3)字节卡住的服务器上的网络负载条件是什么?重负载导致输出错误,导致套接字队列没有被清空? (也可能存在NIC错误,其中在遇到某些错误情况后,NIC缓冲区没有刷新,或者无法恢复传输,并且某种监视器会清除这种情况)

有关上述两项的更多信息肯定会有所帮助。

答案 3 :(得分:0)

您是否确定在读取调用中遇到的线程与发送数据的线程相同?是否有可能实际涉及的线程被阻塞在其他一些活动上,而你的stackdump显示其他无辜的线程恰好正在执行socket i / o?自从我使用Java以来​​已经有一段时间了,但我依稀记得使用套接字的JVM。

我会检查所有接收方,看看其中一个是否是预期的接收器,而是做了15分钟的其他事情。

它在一个位置与另一个位置工作的事实通常指向应用程序计时错误,而不是数据中心问题。