我应该从哪里开始调查 SocketTimeoutException:读取超时

2022-09-01 21:18:38

我时不时地在日志中看到以下堆栈跟踪,其中,套接字超时尝试从另一台服务器访问内容。我的问题是,对于在 Linux 上的 Weblogic 上运行的 J2EE 应用程序,我应该检查哪些配置设置?我专门寻找以下内容。HttpClienttext/script

  • JVM 超时参数
  • HttpClient参数
  • Weblogic 超时参数或任何其他配置,如线程数等。
  • J2EE 应用程序设置,如 servlet 配置等。
  • 操作系统资源,如线程、文件处理程序和 cpu
  • 可能影响套接字连接的任何其他配置设置
  • 线程转储会有帮助吗?

这是我的代码

HTTPResponse httpClientResponse;
//do some stuff
httpClientResponse.getStatusCode(); // this is where it fails

这是堆栈跟踪

java.net.SocketTimeoutException: Read timed out
at jrockit.net.SocketNativeIO.readBytesPinned(Native Method)
at jrockit.net.SocketNativeIO.socketRead(SocketNativeIO.java:32)
at java.net.SocketInputStream.socketRead0(SocketInputStream.java)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at HTTPClient.BufferedInputStream.fillBuff(BufferedInputStream.java:206)
at HTTPClient.BufferedInputStream.read(BufferedInputStream.java:126)
at HTTPClient.StreamDemultiplexor.read(StreamDemultiplexor.java:356)
at HTTPClient.RespInputStream.read(RespInputStream.java:147)
at HTTPClient.RespInputStream.read(RespInputStream.java:108)
at HTTPClient.Response.readResponseHeaders(Response.java:1123)
at HTTPClient.Response.getHeaders(Response.java:846)
at HTTPClient.Response.getStatusCode(Response.java:331)
at HTTPClient.RetryModule.responsePhase1Handler(RetryModule.java:92)
at HTTPClient.HTTPResponse.handleResponseImpl(HTTPResponse.java:872)
at HTTPClient.HTTPResponse.access$000(HTTPResponse.java:62)
at HTTPClient.HTTPResponse$2.run(HTTPResponse.java:839)
at HTTPClient.HTTPResponse$2.run(HTTPResponse.java:837)
at
HTTPClient.HttpClientConfiguration.doAction(HttpClientConfiguration.java:666)
at HTTPClient.HTTPResponse.handleResponse(HTTPResponse.java:837)
at HTTPClient.HTTPResponse.getStatusCode(HTTPResponse.java:242) 

谢谢

我将用下面的调查结果更新我的问题。

  1. 没有设置显式超时,这意味着服务器的 http 会话超时可能会生效。HttpClient
  2. SO_TIMEOUTfor 为 0,这意味着它应该无限期等待。HttpClient

答案 1

分会场 1

根据javadocs,Httpclient似乎没有Socket超时的默认值。要回答更新中的问题 - 会话超时在此处将不起作用。Weblogic 的默认值为会话超时 30 分钟。

服务器表示在用户尚未访问服务器时将在内存中保留的时间量。session timeoutHttpSession

套接字超时是在将数据传输回调用方时保持服务器套接字打开的时间量。这甚至可能是服务器仍在处理和写回数据,但这需要相当长的时间,客户端刚刚超时等待它。

一些链接建议此默认值为60秒,但javadocs不会说任何内容,无论如何,您可以将此值设置为120秒,以查看是否有帮助

http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/params/HttpConnectionParams.html#setSoTimeout(int)

您需要的是计时超时 - 如果清楚的话。含义 - 这些错误是否在传出请求的 30 秒、60 秒或 5 分钟后出现?

我会更改SO_Timeout,然后重试

分会场 2 - 操作系统参数

对于 NDD 值,有一些建议的 BEA 参数,这些参数控制传入连接保持打开状态的时间以及排队的连接数等。在Solaris上,这些都是通过运行获得的

/usr/sbin/ndd -get /dev/tcp tcp_time_wait_interval 
/usr/sbin/ndd -get /dev/tcp tcp_conn_req_max_q 
/usr/sbin/ndd -get /dev/tcp tcp_conn_req_max_q0 
/usr/sbin/ndd -get /dev/tcp tcp_ip_abort_interval 
/usr/sbin/ndd -get /dev/tcp tcp_keepalive_interval 

您能否检查Oracle文档中的Linux上的等效命令,以及它们应设置为哪些值。在 Solaris 上,我的经验是默认值是不够的,需要将它们提升到 BEA(Oracle)建议

分会场3:网络逻辑/外部访问日志

是否已在服务器上启用 HTTP 访问日志?这些失败的请求是以任何响应字节大小显示,还是显示 0 响应大小?返回什么错误代码或 HTTP 状态代码?

或者这些超时的那些根本没有记录在访问日志中?

在这里,我假设发生超时的外部服务器也是Weblogic,如果不是 - 这个问题被定向到外部服务器团队的等效平台。

** 其他 **

通常线程转储会有所帮助,但线程转储应该在存在超时问题的服务器上进行。您是客户端,并且您已成功获得连接,之后在读取响应时该连接超时。那么外部服务器是否过载?缺少线程?中央处理器高?并发请求过多?


答案 2

这里没有涉及的另一个方面是防火墙。

我发现 SocketTimeoutExceptions 通常可能与端口未打开进行通信或防火墙仅阻止来自选定计算机的通信有关。

如果您正在调试某个问题,请确保还要调查尝试通信的两台计算机之间是否存在防火墙,如果有防火墙,请确保端口可用于两者之间的通信。

关于防火墙相关问题的有趣之处在于,它不会让您知道服务器是否已关闭或没有响应。典型的行为是让客户端永远等待。所以你总是被留在黑暗中。服务器端口上的简单 telnet 应显示其是否可用/打开以进行通信。

希望这有帮助。


推荐