软件版本:httpclient4.5.6,httpcore4.4.10,httpclient-cache4.5.6,httpmime4.5.6
最近使用httpclient post调用第三方http服务时出现网路异常,无法获取响应。
org.apache.http.NoHttpResponseException: 139.159.143.73:31820 failed to respond
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:143)
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:57)
at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:261)
at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:165)
at org.apache.http.impl.conn.CPoolProxy.receiveResponseHeader(CPoolProxy.java:167)
at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:272)
at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:124)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:271)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:153)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at org.apache.http.impl.io.AbstractSessionInputBuffer.fillBuffer(AbstractSessionInputBuffer.java:166)
at org.apache.http.impl.io.SocketInputBuffer.fillBuffer(SocketInputBuffer.java:90)
at org.apache.http.impl.io.AbstractSessionInputBuffer.readLine(AbstractSessionInputBuffer.java:281)
at org.apache.http.impl.conn.LoggingSessionInputBuffer.readLine(LoggingSessionInputBuffer.java:115)
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:92)
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:62)
at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:254)
at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:289)
at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:252)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.receiveResponseHeader(ManagedClientConnectionImpl.java:191)
at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:300)
at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:127)
at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:712)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:517)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
刚开始以为是超时时间太短,后延长超时时间后问题依旧。
然后更换了httpclient版本。开始使用了httpclient.4.5.6,后觉得时版本问题,更换了4.2.2。问题依旧。换apache cxf web client,spring .RestTemplate还是执行失败
令人奇怪的是同样的程序在本地mac,windows机器上调用对方服务正常,部署到我们的服务器上调用对方服务异常。后观察发现对于post小报文正常,报文大于1500左右就异常。后来又自己mock了个服务,调用mock服务正常,即使很大报文也正常返回。
接着使用wireshark抓包工具,抓包发现成功的情况每个ack包都可以收到应答,而失败的情况都会丢失应答,导致服务端返回badrequest(设置sotimeout=0能够收到{"timestamp":"2018-11-27T00:40:47.735+0000","status":400,"error":"Bad
Request","message":"I/O error while reading input message; nested
exception is java.net.SocketTimeoutException","path":""}),发送失败的tcp包长度比较长。
本地wireshark抓包
服务器wireshark抓包
猜测可能是由于tcp太大导致服务器无法接受报文导致失败,于是找到设置该参数的地方SocketConfig.custom().setSndBufSize(1024).在本机测试发现设置后tcp包确实小了
本机wireshark包
部署到服务器上结果该参数没起作用(不知道为什么,后续再分析为什么),抓包后发现跟没有设置setSndBufSize一样的效果
后来只好修改了系统服务器的参数/proc/sys/net/ipv4/tcp_mtu_probing(默认为0)
sudo sysctl -w net.ipv4.tcp_mtu_probing=1或者2.如果设置为1请求响应有明显延迟,如果设置为2请求响应速度相对很快
修改后的wireshark抓包
cat /proc/sys/net/ipv4/tcp_congestion_control
cat /proc/sys/net/ipv4/tcp_available_congestion_control
参考:
http://hc.apache.org/httpcomponents-client-4.5.x/tutorial/html/index.html(翻译可以参考https://blog.csdn.net/chenpeng19910926/article/details/71482347)
http://man7.org/linux/man-pages/man7/tcp.7.html
https://www.jianshu.com/p/dfcca2756aed
https://www.cnblogs.com/ggjucheng/archive/2012/01/14/2322659.html
https://www.linuxidc.com/Linux/2013-07/87309.htm
https://www.cnblogs.com/ppsunlight/p/4000455.html
sudo tcpdump -AXvvenn -s 0 'tcp and host 139.159.143.73' -w out.cap