我有一个基于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并在超时后立即重试请求,则重试始终成功.(当然,我首先中止超时请求并释放连接以确保将使用新的套接字.)
思考?想法?是否有一些TCP/IP设置可用于Java或Windows中的注册表设置,以便在丢失的数据包上启用更积极的TCP/IP重试?
您是否完全确定服务器已成功将响应发送到似乎失败的客户端?我的意思是服务器发送了响应,客户端已经将响应发送回服务器.您应该在服务器端使用wireshark看到这一点.如果您确定在服务器端发生了这种情况,并且客户端仍然没有看到任何内容,则需要从服务器中查找更多链.是否涉及代理/反向代理服务器或NAT?
TCP传输被认为是一种可靠的协议,但它不保证传输.您的操作系统的TCP/IP堆栈将非常难以使用TCP重新传输将数据包传输到另一端.如果发生这种情况,你应该在服务器端的wireshark中看到这些.如果您看到过多的TCP重新传输,则通常是网络基础结构问题 - 即错误或配置错误的硬件/接口.TCP重传对于短暂的网络中断非常有效,但在具有较长中断的网络上表现不佳.这是因为TCP/IP堆栈只会在计时器到期后发送重新传输.在每次不成功的重传之后,该计时器通常会加倍.这是为了避免因重传而泛滥已经存在问题的网络.正如您可能想象的那样,这通常会导致应用程序出现各种超时问题.
根据您的网络拓扑,您可能还需要将探测/ wireshark/tcpdump放置在网络中的其他中间位置.这可能需要一些时间来找出数据包的去向.
如果我是你,我将继续使用wireshark进行监控,直到问题再次发生.它很可能会.但是,听起来你最终会发现的就是你已经提到的 - 片状硬件.如果修复片状硬件是不可能的,您可能需要构建额外的应用程序级别超时和重试以尝试在软件中处理该问题.听起来你开始走这条路了.