`
bsr1983
  • 浏览: 1117390 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

httpclient4.x 使用连接池发送https请求使用总结

 
阅读更多
    由于项目中需要用httpclient进行内部服务请求处理,但之前没有是用httpclient中提供的连接池,而是自己封装的一个类似池的结构,一段时间后产生了性能问题,转而尝试通过是用httpclient内部的池进行处理,而且需要支持https的连接。
     所使用的httpclient的版本为4.4.1,一共用到了三个jar:httpclient-4.4.1.jar、httpclient-cache-4.4.1.jar、httpcore-4.4.1.jar。
    所使用的连接池管理器的类为PoolingHttpClientConnectionManager,但httpclient部分参数,包括池的大小,最大路由,缓存,超时这些参数还未做深入研究;
     上代码:
      
  初始化代码:
     public void init()
 {
   try {
   //需要通过以下代码声明对https连接支持
   SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(null,
                   new TrustSelfSignedStrategy())
           .build();
   HostnameVerifier hostnameVerifier = SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
   SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
           sslcontext,hostnameVerifier);
   Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
           .register("http", PlainConnectionSocketFactory.getSocketFactory())
           .register("https", sslsf)
           .build();
   //初始化连接管理器
   poolConnManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
   // Increase max total connection to 200
   poolConnManager.setMaxTotal(maxTotalPool);
   // Increase default max connection per route to 20
   poolConnManager.setDefaultMaxPerRoute(maxConPerRoute);
  } catch (KeyManagementException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (NoSuchAlgorithmException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (KeyStoreException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
//获取连接
 public CloseableHttpClient getConnection()
 {
      CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(poolConnManager).build(); 
      return httpClient;
 }
//发送请求 url为请求url,jsonstr为请求参数
public String post(String url, String jsonStr)
 {
  String returnStr = null;
  //参数检测
  if(url==null||"".equals(url))
  {
   return returnStr;
  }
  try {
   HttpPost httpPost = new HttpPost(url);
   List <NameValuePair> nvps = new ArrayList <NameValuePair>();
   //设置post参数对
   nvps.add(new BasicNameValuePair("jsonstr", jsonStr));
   //设置编码,如果包含中文,一定要进行设置,否则按照系统默认字符集进行转码会出现乱码
   httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
   CloseableHttpResponse response = client.execute(httpPost);
   //获取响应状态码
   int status = response.getStatusLine().getStatusCode();
            if (status >= 200 && status < 300) {
                HttpEntity entity = response.getEntity();
                return entity != null ? EntityUtils.toString(entity,"utf-8") : null;
            } else {
                throw new ClientProtocolException("Unexpected response status: " + status);
            }
  } catch (UnsupportedEncodingException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (ClientProtocolException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  //相应返回值
  return returnStr;
 }
 -------------------------------------------分隔线------------------------------------------------------
  在使用上述代码一段时间后,出现了tomcat异常后死掉的bug,而且是随机出现,没有找到具体原因,最终在加了一堆日志后,分析得知是因为在返回状态码非200的时候,httpclient的连接不会自动断开,需要手工断开,否则在连接达到pool的最大值后,无可用连接,最终导致tomcat死掉。
最后修改的代码如下:
public void init()
	{
		 try {
			SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(null,
			                new TrustSelfSignedStrategy())
			        .build();
			HostnameVerifier hostnameVerifier = SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
			        sslcontext,hostnameVerifier);
			Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
			        .register("http", PlainConnectionSocketFactory.getSocketFactory())
			        .register("https", sslsf)
			        .build();
			poolConnManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
			// Increase max total connection to 200
			poolConnManager.setMaxTotal(maxTotalPool);
			// Increase default max connection per route to 20
			poolConnManager.setDefaultMaxPerRoute(maxConPerRoute);
			SocketConfig socketConfig = SocketConfig.custom().setSoTimeout(socketTimeout).build();
			poolConnManager.setDefaultSocketConfig(socketConfig);
		} catch (Exception e) {
			log.error("InterfacePhpUtilManager init Exception"+e.toString());
		}
	}
	public CloseableHttpClient getConnection()
	{
		RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(connectionRequestTimeout)
				.setConnectTimeout(connectTimeout).setSocketTimeout(socketTimeout).build();
		CloseableHttpClient httpClient = HttpClients.custom()
			        .setConnectionManager(poolConnManager).setDefaultRequestConfig(requestConfig).build();
		if(poolConnManager!=null&&poolConnManager.getTotalStats()!=null)
		{
			log.info("now client pool "+poolConnManager.getTotalStats().toString());
		}
		return httpClient;
	}
  其中输出的连接一共有四个状态,是需要时时关注的,可以作为调整参数的依据,具体含义为:
 
leased :the number of persistent connections tracked by the connection manager currently being used to execute requests.

available :the number idle persistent connections.

pending : the number of connection requests being blocked awaiting a free connection.

max: the maximum number of allowed persistent connections.
    
   需要特别关注pending和leased的值,如果leased的值特别大,接近max,则需要修改max,如果pending的值也比较大,也需要调整max,并考虑设置timeout,可以设置两个timeout,一个是获取连接的timeout,另外一个是获取socket数据的timeout。代码中已经有相关示例了。
 具体获取响应时,要改为如下代码,即在返回的状态码不是200时,要主动关闭连接
public String postPhp(String url, String jsonStr)
	{
		String returnStr = null;
		//参数检测
		if(url==null||"".equals(url))
		{
			return returnStr;
		}
		HttpPost httpPost = new HttpPost(url);
		try {
			
			long currentTime=System.currentTimeMillis();
			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
			nvps.add(new BasicNameValuePair("jsonstr", jsonStr));
			httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
			sysoutLog(currentTime+" 开始发送 请求:url"+url);
			CloseableHttpResponse response = client.execute(httpPost);
			int status = response.getStatusLine().getStatusCode();
            if (status >= 200 && status < 300) {
            	HttpEntity entity = response.getEntity();
                String resopnse="";
                if(entity != null)
                {
                	resopnse=EntityUtils.toString(entity,"utf-8");
                }
                sysoutLog(currentTime+" 接收响应:url"+url+" status="+status);
                return entity != null ? resopnse : null;
            } else {
            	HttpEntity entity = response.getEntity();
            	httpPost.abort();
            	sysoutLog(currentTime+" 接收响应:url"+url+" status="+status+" resopnse="+EntityUtils.toString(entity,"utf-8"));
                throw new ClientProtocolException("Unexpected response status: " + status);
            }
		} catch (Exception e) {
			httpPost.abort();
			log.error(" Exception"+e.toString()+" url="+url+" jsonstr="+jsonStr);
		} 
		return returnStr;
	}
 
 
  
0
0
分享到:
评论

相关推荐

    httpclient4.x官方范例

    此外,HTTPClient 4.x提供了更灵活的配置选项,比如连接管理器,允许自定义连接池大小、超时设置等。 1. **连接管理**:在HTTPClient 4.x中,`PoolingHttpClientConnectionManager`是默认的连接管理器,负责创建、...

    HTTPClient 4.3.X

    这个库为开发者提供了丰富的功能,包括发送HTTP请求,处理响应,管理连接池,处理cookies,以及支持HTTPS等。在4.3.X版本中,它可能包含了性能优化,新特性和bug修复。 描述中提到的链接指向了一个ITEYE博客,虽然...

    httpclient4.3.x及其依赖jar包

    3. **连接管理**:HttpClient提供了强大的连接管理机制,包括连接池,能够有效地复用TCP连接,减少网络延迟。 4. **请求和响应的抽象**:HttpClient将HTTP请求和响应进行了清晰的抽象,方便开发者自定义请求头、...

    httpclientDemo(4.x与4以下的版本)例子

    这个"HttpclientDemo(4.x与4以下的版本)"示例显然涵盖了HttpClient在不同版本间的使用方法,特别是4.x版本和4.x之前的版本之间的差异。在本文中,我们将深入探讨HttpClient的基本概念、主要功能以及在不同版本中的...

    HttpClient3.1.jar

    HttpClient3.1.jar是Apache HttpClient库的一个版本,它在Java编程环境中用于实现HTTP客户端通信。这个库被广泛用于开发需要...在新的项目中,开发者通常会考虑使用更新的版本(如HttpClient 4.x)或替代品,如OkHttp。

    httpclient-4.5.2.jar.zip

    - **执行请求**:使用HttpClient的`execute()`方法发送请求,并获取`HttpResponse`对象。 - **处理响应**:从`HttpResponse`中获取状态码、响应头和响应体,通常通过`EntityUtils`类进行读取。 4. 进阶用法: - ...

    HttpClient所需jar包(全) httpClient.4.13jar

    它为开发者提供了强大的功能,包括但不限于发起GET、POST等HTTP方法的请求,处理响应,管理连接池,以及支持HTTPS和其他高级特性。HttpClient 4.13版本是这个库的一个较新版本,包含了一系列的改进和修复。 在Java...

    commons-httpclient-3.0.jar JAVA中使用HttpClient可以用到

    1. **连接管理**:HttpClient支持连接池,可以通过HttpConnectionManager来管理多个连接,提高性能和效率。 2. **认证和安全**:HttpClient支持多种认证机制,包括基本认证、摘要认证等。同时,它也支持HTTPS,提供...

    httpclient4.2.2.zip

    3. 执行请求:通过HttpClient实例的execute方法发送请求。 4. 处理响应:获取HttpEntity,从中读取响应数据,如状态码、响应头和响应体内容。 5. 关闭资源:执行完请求后,记得关闭HttpClient实例和HttpEntity,释放...

    初学java,未有小成 --- httpClient4.jar包学习

    HttpClient 4.x版本是Apache基金会开发的一个开放源码库,广泛应用于Web服务的客户端实现,允许开发者发送HTTP请求并处理响应。在这个初学阶段的学习中,HttpClient4.jar包将成为你探索网络通信的关键。 首先,了解...

    httpclient.jar4.4及4.5版本和httpcore.jar和commons-logging.jar.rar

    最后,使用HttpClient的execute方法发送请求,并获取HttpResponse对象以处理响应。 在实际应用中,HTTPClient库的高级特性包括: 1. **多路复用**:HTTP/2协议支持多路复用,允许多个HTTP请求共享一个TCP连接,...

    httpclient.zip

    - 发送请求:通过`execute`方法发送请求,获取`HttpResponse`对象。 - 处理响应:`HttpResponse`包含状态码、头部信息和实体内容,可以通过`EntityUtils`类解析实体。 3. **连接管理**: - 连接池:HttpClient...

    httpclient-4.5.2.jar安卓网络请求

    4. 执行请求:使用HttpClient的`execute`方法发送请求,并获取响应: ```java CloseableHttpResponse response = httpClient.execute(httpGet); ``` 5. 处理响应:解析响应状态和内容,例如: ```java ...

    使用httpClient访问https+443端口号。

    6. **执行请求**:使用HttpClient实例的`execute`方法发送请求,并获取`HttpResponse`。 7. **处理响应**:解析`HttpResponse`,获取状态码,读取响应体,可能需要使用`EntityUtils`类。 8. **关闭连接**:记得在...

    commons-httpclient-3.0.jar

    1. **连接管理**:HttpClient允许开发者设置连接池,有效管理HTTP连接,避免频繁创建和关闭连接,提高性能。它支持多线程环境下的并发连接,并且可以设置连接超时、重试策略等。 2. **支持多种HTTP方法**:除了基本...

    最新org.apache.commons.httpclient.rar

    3. **使用方式**:在项目中引入`org.apache.commons.httpclient-3.1.0.jar`后,可以通过创建`HttpClient`实例,配置各种参数,然后调用`executeMethod`方法来发送HTTP请求。例如,发送一个GET请求: ```java ...

    commons-httpclient-3.1.jar

    《Apache HttpClient 3.1详解及其在Java中的应用》 Apache HttpClient是一个强大的HTTP客户端实现库...然而,由于HttpClient 3.x已被4.x系列取代,虽然3.1仍可使用,但推荐更新到更现代的版本以获取更多的特性和改进。

    commons-httpclient,java中使用httpclient中使用的扩展工具

    11. **连接池管理**:`PoolingHttpClientConnectionManager`是HttpClient 4.x版本中的连接池管理器,可以更高效地复用TCP连接,减少建立新连接的开销。 在实际应用中,你需要根据项目需求配置HttpClient实例,例如...

    使用HttpClient必须的jar包

    在压缩包中的"使用HttpClient发送json必须的jar包"可能包含了处理JSON数据所必需的库,如`gson-x.x.x.jar`或`jackson-core-x.x.x.jar`、`jackson-databind-x.x.x.jar`等。 在"使用说明.txt"中,通常会详细阐述如何...

Global site tag (gtag.js) - Google Analytics