首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

HttpClient使用心得

做过Java web开发的朋友们,应该大部分都用过Apatch HttpClient工具类库,最近在维护公司一个老项目时,遇到了由于HttpClient使用不当导致的线上问题,针对这些问题总结了一些心得,分享给大家,如有不正确的地方欢迎留言指出。

1、尽量复用HttpClient对象

初学者一般使用HttpClient工具,都是newHttpClient()对象出来,然后结合相关的HttpMethod对象执行Http请求操作,如下实例代码:

HttpClient client = new HttpClient();

String responseStr = null;

try {

intstatusCode = client.executeMethod(method);

if(statusCode != HttpStatus.SC_OK) {

log.error("服务器{},返回码异常{}", url, statusCode);

}else {

InputStream inputStream = method.getResponseBodyAsStream();

StringBuilder sBuilder = newStringBuilder();

charbuf[] = new char[1024];

intreadNum;

while(-1 != (readNum = is.read(buf, 0, BUF_LEN))) {

sBuilder.append(buf,0, readNum);

}

//获取服务器返回的内容

responseStr= sBuilder.toString();

}

} catch (HttpException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}finally{

method.releaseConnection();

}

当应用系统多个模块需要执行Http请求时,若按照上述例子实现代码,会存在多份类似的代码,应用并发运行时,可能存在同时实例化多个HttpClient实例的情况,会造成系统资源的浪费,Apatch官方的性能指导文档建议可以根据系统实际请求情况,全应用共用一个单例HttpClient对象或每个组件的请求共用一个HttpClient对象。

当共用一个HttpClient对象时,需要考虑并发场景,避免造成多线程问题。在公司的系统就遇到这样一个问题,概率存在Http请求执行失败的情况,查看日志发现报各种奇怪的异常,有java.net.SocketException: Connection reset、java.io.IOException:CRLF expected at end of chunk、java.io.IOException: Bad chunk size等,一时不知所措,再细看日志发现出异常前存在如下警告日志:“SimpleHttpConnectionManager being used incorrectly. Be sure that HttpMethod.releaseConnection()is always called and that only one thread and/or method is using thisconnection manager at a time.”,大概的意思是SimpleHttpConnectionManager只适用于单线程场景,查资料发现当用不带参数的构造函数实例化HttpClient对象时,内部会实例化一个SimpleHttpConnectionManager对象,该连接管理对象没有采用连接池的方式管理HttpConnection对象,仅管理一个HttpConnection对象,不能适用于多线程场景,在多线程场景下SimpleHttpConnectionManager不能保证每个线程获取到单独的HttpConnection对象,因此易造成多个线程共用HttpConnection对象的情况,从而造成HttpConnection对象操作异常。从公司日志看出连续两次Http请求方法执行的时间间隔很短时(比如几十ms),会出现上述异常。HttpClient工具包中提供了一个MultiThreadedHttpConnectionManager类,可用于多线程场景下的Http连接,在实例化HttpClient对象时,在构造函数中传递MultiThreadedHttpConnectionManager对象,MultiThreadedHttpConnectionManager类以连接池的方式管理HttpConnection,确保每个HttpMethod方法执行时获取独立的HttpConnection对象,避免多线程问题。

当以默认的构造函数实例化非单例的HttpClient对象时,当请求执行完成时不再需要该HttpClient对象时,需要及时关闭HttpMethod使用到的HttpConnection对象。通常情况下都是调用HttpMethod.releaseConnection()方法释放方法对象占用的连接,通过跟踪该方法的代码,发现该方法仅仅是将HttpConnection对象归还给SimpleHttpConnectionManager,并未执行HttpConnection的close方法关闭底层的TCP连接,可以通过HttpClient对象获取SimpleHttpConnectionManager对象,并调用其closeIdleConnections方法关闭连接。

2、学会设置HttpClient连接相关参数

3、避免在数据库事务方法中使用耗时的请求操作

在数据库事务方法中,需要避免使用耗时的请求操作,避免导致事务超时异常。公司的应用就遇到一个这样的问题:第三方平台退款接口异常,导致退款事务超时,实际退款完成了,但是将退款记录保存到数据中时hibernate报异常了,平时设计代码时应将耗时的网络请求操作从事务中剥离,可考虑采用异步的方式执行这些耗时操作,例如消息队列。

1、http://hc.apache.org/httpclient-3.x/performance.html

2、http://hc.apache.org/httpclient-3.x/preference-api.html

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20171229G0KJ5C00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券