在与第三方系统经过http交互数据的过程当中,抓包发现每次TCP链接都是异常关闭,报文以下:html
能够看到,由我方发起3次握手创建链接,而后发送http请求,对方响应数据,我方ACK后直接发RST包(图中蓝色阴影部分),将链接异常关闭,不只没有复用链接,且不是经过4次挥手来关闭链接。java
关于RST包参考:http://blog.csdn.net/erlib/ar...git
HttpClient 4.5.2 释放链接API使用方式不正确github
问题代码以下(已简化):tcp
private boolean isCheckSuccess() { CloseableHttpResponse response = null; try { // 经过HttpClientBuilder建立CloseableHttpClient httpClient = HttpClientFactory.createHttpClient(); request = initCheckRequest(); response = httpClient.execute(request); if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { return true; } } finally { // 释放链接 if(request != null) { request.releaseConnection(); } } return false; } //构造请求参数 private static HttpPost initCheckRequest() throws IOException { HttpPost request = new HttpPost(callBackUrl); request.setHeader("contentType", ContentTypeEnum.JSON.getDesc()); List<NameValuePair> params = new ArrayList<>(); params.add(new BasicNameValuePair("developer_id", "111")); params.add(new BasicNameValuePair("sign", "sign")); HttpEntity postParams = new UrlEncodedFormEntity(params); request.setEntity(postParams); return request; }
根据释放链接处代码和抓包分析来看,request.releaseConnection();
每次是发TCP RST包来关闭链接post
既然是释放链接不对,则修改代码为以下:ui
finally { if(response != null) { try { EntityUtils.consume(response.getEntity()); response.close(); } catch (IOException e) { logger.error("close http error", e); } } }
正确方式为:
关闭内容流后再关闭响应自己。spa
若是不关闭IO流,直接response.close();
则结果是链接不能复用,直接经过4次挥手断开TCP链接。.net
链接池释放链接的时候,并不会直接对TCP链接的状态有任何改变,只是维护了两个Set,leased和avaliabled,leased表明被占用的链接集合,avaliabled表明可用的链接的集合,释放链接的时候仅仅是将链接从leased中remove掉了,并把链接放到avaliabled集合中code
本人blog:https://my.oschina.net/hebaod...
TCP RST相关
http://www.cnblogs.com/JohnAB...
http://blog.csdn.net/erlib/ar...
http://lovestblog.cn/blog/201...
https://my.oschina.net/costax...
HttpClient相关
https://www.cnblogs.com/likai...
http://liangbizhi.github.io/h...