由于httpClient调用导致的ESTABLISHED过多和 Connection rest by peer 异常
问题描述:
生产环境突然之间出现了大量的Connection rest by peer.后来使用netstat -an | grep 服务端口号发现有大量来自A10服务器的ESTABLISHED连接,多的时候单台达到1万多,总连接数达到3万多。后来查看A10服务器发现,连接数来自同一个客户,于是猜测可能是该用户在请求时,每一次都会建立一个新的连接,并且该连接没有释放。
于是联系该用户,查看他们的建立请求连接的代码:
发现客户使用了apache的httpClient的method.releaseConnection()来释放资源。经过同事的提醒说这样的释放资源其实是有问题的,于是在网上找到了解决相关介绍:
先介绍一下,做了哪些工作以及后期的改正工作:
1.首先在A10限制每一个ip可以访问的连接数,
2.在A10配置所有的连接请求为短连接
3.代码层面,通知客户修改其调用程序
4.在服务层面应该禁止长连接的建立,都保持为短连接。
以下是httpClient的使用介绍:
http://www.myexception.cn/internet/1552774.html
HttpClient引起的TCP连接数高的问题分析
【问题现象】
系统上线后出现TCP连接数超过预期阀值,最高值达到8K左右,新上线代码中包含了一文件上传操作,使用的是apache的commons-httpclient包。
【问题分析】
1、先确认是否存在连接未关闭问题引起的。
观察发现,TCP连接数不是一直在增长,而是会有所下降。并且当业务低峰期TCP连接数TCP连接数会降到100左右,这说明TCP连接还是会关闭。
2、确定居高不下的TCP使用情况
使用"netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'"命令发现,处于ESTABLISHED状态的连接数最多,在查看了一下处于ESTABLISHED状态的目的IP,基本上都是文件服务器的 IP,这说明还是跟新增加的文件上传操作有关。但是按照代码的逻辑来看,文件上传操作是多线程处理的,一个线程处理一个上传操作,线程池中一共有10个线 程,照此分析正常的话应该有10个左右与文件服务器的链接,不应该出现几千个链接。因此怀疑是连接没有主动释放,而是等待连接超时才开始释放。
3、为什么会连接超时
查看了文件上传部分代码,主要代码如下:
HttpClient client = new HttpClient();
MultipartPostMethod method = new MultipartPostMethod(config .getUploadInterface());
try{
client.executeMethod(method);
}catch (Exception e){
throw e;
}finally{
method.releaseConnection();
}
从代码里看是已经释放连接了,但是从结果上看没有释放连接,那就产生一个问题,这个地方真的能释放连接吗?我们在释放连接后面增加一行测试代码来看看:
HttpConnection conn = client.getHttpConnectionManager().getConnection(client.getHostConfiguration());
System.out.println(conn.isOpen());
打印出的结果是true,也就是说虽然调用了releaseConnection,但是并没有释放连接!!
4、分析commons-httpclient相关代码
现在怀疑是我们使用的方式不对了,继续分析一下commons-https包中相关代码,首先看一下method.releaseConnection()的代码实现:
public void releaseConnection() {
try {
if (this.responseStream != null) {
try {
// FYI - this may indirectly invoke responseBodyConsumed.
this.responseStream.close();
} catch (IOException ignore) {
}
}
} finally {
ensureConnectionRelease();
}
}
private void ensureConnectionRelease() {
if (responseConnection != null) {
responseConnection.releaseConnection();
responseConnection = null;
}
}
经过debug发现responseStream为null,并且responseConnection也为null,这样改调用就没有实际意义。那么我们应该怎么来释放连接呢?
5、继续分析代码
我们发现在org.apache.commons.httpclient.HttpMethodDirector类的第208行已经在finally中释放连接了:
finally {
if (this.conn != null) {
this.conn.setLocked(false);
}
// If the response has been fully processed, return the connection
// to the pool. Use this flag, rather than other tests (like
// responseStream == null), as subclasses, might reset the stream,
// for example, reading the entire response into a file and then
// setting the file as the stream.
if (
(releaseConnection || method.getResponseBodyAsStream() == null)
&& this.conn != null
) {
this.conn.releaseConnection();
}
}
public void releaseConnection(HttpConnection conn) {
if (conn != httpConnection) {
throw new IllegalStateException("Unexpected release of an unknown connection.");
} finishLastResponse(httpConnection); inUse = false; // track the time the connection was made idle
idleStartTime = System.currentTimeMillis();
}
这个地方我们可以看到了所谓的释放连接并不是真的释放,还是return the connection to pool,照此分析,我们每个线程中new了一个HttpClient类,而每个HttpClient类中的链接都是没有close的,只是归还到 httpClient中的pool而已,这些连接也必须等到连接超时才会被释放,由此可以分析出来连接数上涨的原因。那么我们应该怎么使用呢?按照代码的 设计,看起来httpclient应该是单例的,但是在httpClient类的javadoc中并没有关于线程安全方面的说明,为此我们再回到官网上看 相关文档,在文档(http://hc.apache.org/httpclient-3.x/performance.html)上我们看到如下的说 明:
HttpClient is fully thread-safe when used with a thread-safe connection manager such as MultiThreadedHttpConnectionManager
这说明在多线程环境下应该使用一个全局单例的HttpClient,并且使用MultiThreadHttpConnectionManager来管理Connection。
【相关结论】
1、HttpClient内部使用了池化技术,内部的链接是为了复用。在多线程条件下,可以使用一个全局的HttpClient实例,并且使用MultiThreadHttpConnectionManager来管理Connection。
2、使用开源软件之前一定要读读相关代码,看看官方推荐使用方式。
3、在解决此问题后,读了读httpclient中其他包中的代码,在读的时候发现对于理解http协议帮助很大,特别是文件上传,长连接,auth鉴权等。
由于httpClient调用导致的ESTABLISHED过多和 Connection rest by peer 异常的更多相关文章
- C# DllImport“调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配 ”
调用外部dll时,出现如下问题 C# DllImport“调用导致堆栈不对称.原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配.请检查 PInvoke 签名的调用约定和参数与非托管的目标 ...
- httpclient 调用WebAPI
1.创建webapi项目,提供接口方法如下: /// <summary> /// 获取租户.位置下的所有传感器 /// </summary> /// <returns&g ...
- httpclient调用https
httpclient调用https报错: Exception in thread "main" java.lang.Exception: sun.security.validato ...
- 解决:对 PInvoke 函数的调用导致堆栈不对称问题 <转载>
问题描述: 在使用托管代码调用非托管代码时,发生“对 PInvoke 函数“UseTwiHikVisionDllTest!UseTwiHikVisionDllTest.TwiHikVision::Ge ...
- 对 PInvoke 函数“WinVideo!WinVideo.webcam::SendMessage”的调用导致堆栈不对称
从.NET1.1升级到.NET2.0时出现的PInvokeStackImbalance错误微软官方的解释 (http://msdn2.microsoft.com/zh-cn/library/0htdy ...
- 解决:对 PInvoke 函数的调用导致堆栈不对称问题
解决:对 PInvoke 函数的调用导致堆栈不对称问题 问题描述: 在使用托管代码调用非托管代码时,发生“对 PInvoke 函数“UseTwiHikVisionDllTest!UseTwiHikVi ...
- 通过HttpClient 调用ASP.NET Web API
在前面两篇文章中我们介绍了ASP.NET Web API的基本知识和原理,并且通过简单的实例了解了它的基本(CRUD)操作.我们是通过JQuery和Ajax对Web API进行数据操作.这一篇我们来介 ...
- SpringMVC,MyBatis项目中兼容Oracle和MySql的解决方案及其项目环境搭建配置、web项目中的单元测试写法、HttpClient调用post请求等案例
要搭建的项目的项目结构如下(使用的框架为:Spring.SpingMVC.MyBatis): 2.pom.xml中的配置如下(注意,本工程分为几个小的子工程,另外两个工程最终是jar包): 其中 ...
- Asp.Net MVC WebAPI的创建与前台Jquery ajax后台HttpClient调用详解
1.什么是WebApi,它有什么用途? Web API是一个比较宽泛的概念.这里我们提到Web API特指ASP.NET MVC Web API.在新出的MVC中,增加了WebAPI,用于提供REST ...
随机推荐
- 第十三周学习笔记(编辑器选错了重发了这一个 原博客的确周天晚上提交了orz)
并发:逻辑控制流在时间上的重叠. 构造并发程序的方法: 进程 I/O多路复用 线程 基于进程的并发编程 假设我们有两个客户端和一个服务器,服务器正在监听一个监听表述符上的请求.现在假设服务器接受了客户 ...
- read.csv 把 "T" 读成 "TRUE" 的问题
read.csv(text="A,B,T,T", header=FALSE) ## V1 V2 V3 V4 ## 1 A B TRUE TRUE RT, 有的时候R读取数据的时候容 ...
- 网页左上角图标 favicon.ico
显示网页左上角标志图标 <link rel="shortcut icon" type="image/x-icon" href="images/f ...
- 重写ScrollView 解决ScrollView嵌套viewpager事件冲突
import android.content.Context; import android.util.AttributeSet; import android.view.GestureDetecto ...
- word转pdf字体格式变乱的问题
完成word转pdf的功能之后,本地测试没问题,然后发布到服务器上,就遇到了字体变乱的问题,如下: 由于我本地发布后导出没有出现同样情况,而服务器和本地的最大区别在于字体库,于是,把服务器上关于需要用 ...
- 1、C#入门第一课
C# 读作C Sharp,所以程序文件的扩展名为.cs 新建项目-窗体应用程序 所谓的Visual C#就是指的可视化编程,主要在设计窗口布置好自己的控件(一些具有一定功能的小部件,例如如可以点击的按 ...
- 家有学霸的CEO
小余老师说 http://learning.sohu.com/20161101/n471998591.shtml
- dbms_stats包更新、导出、导入、锁定统计信息
dbms_stats包问世以后,我们可通过一种新的方式来为CBO收集统计数据.目前,已经不再推荐使用老式的Analyze分析表和dbms_utility方法来生成CBO统计数据.dbms_stats能 ...
- [solr] - IKAnalyzer 分词加入
1.下载IK Analyzer中文分词器:http://ik-analyzer.googlecode.com/files/IK%20Analyzer%202012FF_hf1.zip 2.解压出zip ...
- -include和sinclude 作用
-include和sinclude 如果有文件没有找到的话,make会生成一条警告信息,但不会马上出现致命错误.它 会继续载入其它的文件,一旦完成makefile的读取,make会再重试这些没有找 ...