我有一个基于Web的应用程序和一个客户端,都是用Java编写的。对于它的价值,客户端和服务器都在Windows上。客户端通过Apache HttpClient发出HTTP GET。服务器阻塞最多一分钟,如果在该分钟内没有消息到达客户端,则服务器返回HTTP 204 No Content。否则,只要为客户端准备好消息,就会以HTTP 200的正文返回它。
这让我感到困惑:对于特定客户端子集间歇性地 - 始终是客户端网络连接明显不稳定 - 客户端发出GET,服务器接收并处理GET,但是客户永远坐着。启用客户端的调试日志,我看到HttpClient仍在等待响应的第一行。
服务器上没有抛出异常,至少在任何地方都没有记录,不是由Tomcat记录,而是由我的webapp记录。根据调试日志,服务器成功响应客户端的每一个迹象都表明。但是,客户没有显示收到任何东西的迹象。客户端在HttpClient.executeMethod中无限期挂起。在会话超时并且客户端采取导致另一个线程发出HTTP POST的操作后,这变得很明显。当然,POST失败,因为会话已过期。在某些情况下,会话到期与发出POST并发现此事实的客户端之间已经过了小时。在整个时间内,executeMethod
仍在等待HTTP响应行。
当我使用WireShark查看线路级别的实际情况时,不会发生此故障。也就是说,对于特定客户端,这种故障将在几个小时内发生,但是当WireShark在两端运行时,这些相同的客户端将在14小时内运行一夜,而不会出现故障。
还有其他人遇到过这样的事吗?世界上有什么可以造成它?我认为即使在短期网络故障中,TCP / IP也可以保证数据包传输。如果我设置了SO_TIMEOUT并在超时后立即重试请求,则重试始终成功。 (当然,我首先abort超时请求并释放连接以确保使用新的套接字。)
思考?想法?是否有一些TCP / IP设置可用于Java或Windows中的注册表设置,以便在丢失的数据包上启用更积极的TCP / IP重试?
答案 0 :(得分:8)
您是否完全确定服务器已成功将响应发送到似乎失败的客户端?我的意思是服务器发送了响应,客户端已经将响应发送回服务器。你应该在服务器端使用wireshark看到这个。如果您确定在服务器端发生了这种情况,并且客户端仍然没有看到任何内容,则需要从服务器中查找更多链。是否涉及代理/反向代理服务器或NAT?
TCP传输被认为是一种可靠的协议,但不保证传输。您的操作系统的TCP / IP堆栈将非常难以使用TCP重新传输将数据包传输到另一端。如果发生这种情况,你应该在服务器端的wireshark中看到这些。如果您看到过多的TCP重新传输,则通常是网络基础结构问题 - 即错误或配置错误的硬件/接口。 TCP重传对于短暂的网络中断非常有效,但在具有较长中断的网络上表现不佳。这是因为TCP / IP堆栈只会在计时器到期后发送重新传输。在每次不成功的重传之后,该计时器通常会加倍。这是为了避免因重传而泛滥已经存在问题的网络。正如您可能想象的那样,这通常会导致应用程序出现各种超时问题。
根据您的网络拓扑,您可能还需要将探测/ wireshark / tcpdump放置在网络中的其他中间位置。这可能需要一些时间来找出数据包的去向。
如果我是你,我将继续用wireshark监控所有问题,直到问题再次发生。它很可能会。但是,听起来你最终会发现的就是你已经提到的 - 片状硬件。如果修复片状硬件是不可能的,您可能需要构建额外的应用程序级别超时和重试以尝试在软件中处理该问题。听起来你开始走这条路了。
答案 1 :(得分:2)
忘记刷新或关闭主机端的插座可能会间歇性地产生这种效果,这取决于可能受到任何监控机制影响的时序。
特别是忘记关闭会让套接字悬空,直到GC回收它并调用finalize()。
答案 2 :(得分:2)
如果您正在使用长时间运行的GET,那么您应该在服务器超时的两倍时在客户端超时,如您所发现的那样。
在客户端发送消息并期望响应的TCP上,如果服务器崩溃并重新启动(比如示例),那么客户端仍然在等待套接字以获取响应服务器,但服务器不再侦听该套接字。
一旦客户端在该套接字上发送更多数据,客户端将只发现套接字在服务器端关闭,服务器拒绝这些新数据,并关闭套接字。
这就是为什么你应该对请求有客户端超时。
但是,由于您的服务器没有崩溃,如果服务器是多线程的,并且该客户端的线程套接字已关闭,但在那个时间(持续时间分钟),客户端发生了连接中断,那么终端套接字会动摇我的丢失,并且由于您没有从客户端向服务器发送更多数据,您的客户端再次被搁置。这将与您的剥落连接观察相关联。
答案 3 :(得分:1)
我本身没有看过这个,但是我看到了大型UDP数据报的类似问题,导致IP碎片导致拥塞并最终丢弃以太网帧。由于这是TCP / IP,我不希望IP碎片成为一个大问题,因为它是一个基于流的协议。
我要注意的一件事是 TCP不保证交付!它不能。它保证的是,如果您发送字节A 后跟字节B ,那么在收到字节B >字节A 。
话虽如此,我会将客户机和监控机器连接到集线器。在监控机器上运行Wireshark,您应该能够看到正在发生的事情。我确实遇到了与HTTP请求之间的空白处理和不正确的HTTP块大小相关的问题。这两个问题都是由于手写的HTTP堆栈造成的,所以如果您使用的是片状堆栈,这只是一个问题。
答案 4 :(得分:0)
这些计算机是否安装了病毒/恶意软件?使用wireshark安装winpcap(http://www.winpcap.org/)可能会覆盖恶意软件所做的更改(或者恶意软件可能只是检测到它正在被监控而不会尝试任何可疑的东西)。
答案 5 :(得分:0)
如果您丢失数据,很可能是因为软件错误,无论是在读取还是写入库中。