前一段时间公司项目在利用Apache HttpClient做网络请求的时候,经常拿不到返回结果,试了很多方法都没有结果。尤其是当kt40扫描程序和流水线控制程序同时运作的时候,程序经常收不到后台返回的结果,而后台明明是有值的。后来,通过度娘,最终解决问题。
Apache HttpClient应该是最常用的Java http组件了。这货有个坑爹的地方,Apache HttpClient如果对方不回应,或者网络原因不返回了,那么HttpClient会一直阻塞。这种情况在公网可能比较容易碰到。在内网时,也有一次因为一台中转的nginx挂掉而导致hessian请求长时间阻塞。
因为Http Client默认的SO_TIMEOUT是0,即一直等待。
这个问题,在帮同事查找问题时碰到好几次了,可能是大家潜意识里认为Http请求是即时的,失败的话也很快返回。
Apache HttpClient的示例也没提到要设置TimeOut,这也是比较坑爹的地方。一个库如果没有默认阻止用户去范错误,那么你也应当在文档,示例代码里提醒用户不要范错误。
有三个可以设置time out 的参数:
HttpClient httpClient = new DefaultHttpClient(); //或者DefaultHttpClient httpClient = new DefaultHttpClient();
<span style="color:#ff0000;">httpClient.getParams().setIntParameter(CoreConnectionPNames.SO_LINGER, value);</span>
httpClient.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 3000);
httpClient.getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 3000);
其中HttpClient 是接口,DefaultHttpClient是实现这个接口的子类
最开始,我只设置SO_TIMEOUT和CONNECTION_TIMEOUT这俩个参数,设置超时,发现无效,后来通过查API,增加了以上红色代码,问题解决。我们都知道,SO_TIMEOUT设置的是socket的超时时间,CONNECTION_TIMEOUT设置的是连接超时的时间,单位都为毫秒。那么SO_LINGER到底是什么鬼,见如下API:
SO_LINGER
static final String SO_LINGER
Sets SO_LINGER with the specified linger time in seconds. The maximum timeout value is platform specific. Value 0 implies that the option is disabled. Value -1 implies that the JRE default is used. The setting only affects socket close.
This parameter expects a value of type Integer.
大致的意思是,设置socket指定持续的时间,以秒为单位,最大超时的值是特定于平台的。值0意味着选项是禁用的。值1意味着JRE默认使用。设置只影响到套接字关闭。也就是说重新设置套接字关闭的时间。