优秀的编程知识分享平台

网站首页 > 技术文章 正文

Java Web之HttpClient请求连接池连接池

nanyue 2024-08-03 18:12:04 技术文章 6 ℃

1、httpClient请求连接池使用案例

1.1、maven

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>

1.2 配置文件

<bean id="httpClientConnectionManager"
 
class="org.apache.http.impl.conn.PoolingHttpClientConnectionManager" destroy‐method="close">
<!‐‐ 最大连接数 ‐‐>
<property name="maxTotal" value="200" />
 
<!‐‐ 设置每个主机地址的并发数 ‐‐>
<property name="defaultMaxPerRoute" value="100" />
</bean>
 
<!‐‐ httpclient对象构建器 ‐‐>
<bean id="httpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder">
<!‐‐ 设置连接管理器 ‐‐>
<property name="connectionManager" ref="httpClientConnectionManager" />
</bean>
 
<!‐‐ 定义Httpclient对象 ‐‐>
<bean id="httpClient" class="org.apache.http.impl.client.CloseableHttpClient"
factory‐bean="httpClientBuilder" factory‐method="build" scope="prototype">
</bean>
 
<!‐‐ 定义清理无效连接 ‐‐>
<bean class="com.zz.pay.web.task.IdleConnectionEvictor
" destroy‐method="shutdown">
<constructor‐arg index="0" ref="httpClientConnectionManager" />
</bean>
 
<bean id="requestConfigBuilder" class="org.apache.http.client.config.RequestConfig.Builder">
<!‐‐ 创建连接的最长时间 ‐‐>
<property name="connectTimeout" value="1000"/>
<!‐‐ 从连接池中获取到连接的最长时间 ‐‐>
<property name="connectionRequestTimeout" value="500"/>
<!‐‐ 数据传输的最长时间 ‐‐>
<property name="socketTimeout" value="10000"/>

1.3 、连接回收策略

import java.util.concurrent.TimeUnit;
 
import org.apache.http.conn.HttpClientConnectionManager; public class IdleConnectionEvictor extends Thread {
private final HttpClientConnectionManager connMgr; private volatile boolean shutdown;
public IdleConnectionEvictor(HttpClientConnectionManager connMgr) { this.connMgr = connMgr;
// 启动当前线程
this.start();
}
 
@Override
public void run() { try {
while (!shutdown) { synchronized (this) {
wait(5000);
// 关闭失效的连接
connMgr.closeExpiredConnections();
// 可选的, 关闭30秒内不活动的连接
connMgr.closeIdleConnections(30, TimeUnit.SECONDS);
}
}
} catch (InterruptedException ex) {
// 结束
}
}
 
 
public void shutdown() { shutdown = true; synchronized (this) {
notifyAll();
}
}

1.4 HttpClientService

package com.zz.pay.serviceImpl;

import com.alibaba.fastjson.JSONObject;
import com.zz.pay.service.HttpClientService;
import org.apache.commons.lang.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
public class HttpClientServiceImpl implements HttpClientService {

 private static final Logger logger = LoggerFactory.getLogger(HttpClientServiceImpl.class);
 @Autowired
 private CloseableHttpClient httpClient;
 @Autowired
 private RequestConfig requestConfig;
 @Autowired
 private PoolingHttpClientConnectionManager poolingHttpClientConnectionManager;

 @Override
 public String doGet(String url) {
 if (StringUtils.isBlank(url)){
 logger.error("request url is empty");
 return null;
 }
 HttpGet httpGet = new HttpGet(url);
 httpGet.setConfig(this.requestConfig);
 CloseableHttpResponse response = null;
 try {
 response = httpClient.execute(httpGet);
 if (response.getStatusLine().getStatusCode() == 200) {
 return EntityUtils.toString(response.getEntity(), "UTF-8");
 }
 } catch (IOException e) {
 e.printStackTrace();
 } finally {
 if (response != null) {
 try {
 response.close();
 } catch (IOException e) {
 logger.error("response close() error info {}", e.getMessage());
 }
 }
 logger.info("poolstas {}", poolingHttpClientConnectionManager.getTotalStats());
 }
 return null;
 }

 @Override
 public String doGet(String url, Map<String, String> params) {
 try {
 if (StringUtils.isBlank(url)){
 logger.error("request url is empty");
 return null;
 }
 URIBuilder uriBuilder = new URIBuilder(url);
 Set<String> keys = params.keySet();
 for (String key :
 keys) {
 uriBuilder.addParameter(key, params.get(key));
 }
 this.doGet(uriBuilder.toString());
 } catch (URISyntaxException e) {
 e.printStackTrace();
 }
 return null;
 }

 @Override
 public String doPost(String url) {
 if (StringUtils.isBlank(url)){
 logger.error("request url is empty");
 return null;
 }
 return this.doPost(url, null);
 }

 @Override
 public String doPost(String url, Map<String, String> params) {
 if (StringUtils.isBlank(url)){
 logger.error("request url is empty");
 return null;
 }
 //post请求
 HttpPost httpPost = new HttpPost(url);
 List<NameValuePair> parameters = null;
 if (null != params) {
 parameters = new ArrayList<>();
 Set<String> keys = params.keySet();
 for (String key : keys ) {
 parameters.add( new BasicNameValuePair(key, params.get(key)));
 }
 }
 CloseableHttpResponse response = null;
 //表单实体
 try {
 UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters, "UTF-8");
 httpPost.setConfig(this.requestConfig);
 //表单设置到请求中
 httpPost.setEntity(formEntity);
 response = httpClient.execute(httpPost);
 if (response.getStatusLine().getStatusCode() == 200) {
 return EntityUtils.toString(response.getEntity(),"UTF-8");
 }
 } catch (UnsupportedEncodingException e) {
 e.printStackTrace();
 } catch (ClientProtocolException e) {
 e.printStackTrace();
 } catch (IOException e) {
 e.printStackTrace();
 }finally {
 if(response != null){
 try {
 response.close();
 } catch (IOException e) {
 e.printStackTrace();
 logger.error("response close() error info {}", e.getMessage());
 }
 }
 logger.info("poolstas {}", poolingHttpClientConnectionManager.getTotalStats());
 }
 return null;
 }

 @Override
 public String doPost(String url, String json, String str) {
 if (StringUtils.isBlank(url)){
 logger.error("request url is empty");
 return null;
 }
 HttpPost httpPost = new HttpPost(url);
 CloseableHttpResponse response = null;
 if (json != null){
 StringEntity stringEntity = new StringEntity(json, ContentType.APPLICATION_JSON);
 httpPost.setEntity(stringEntity);
 }
 httpPost.setConfig(this.requestConfig);
 try {
 response = httpClient.execute(httpPost);
 logger.info("response {}", JSONObject.toJSONString(response));
 if(response.getStatusLine().getStatusCode() == 200){
 return EntityUtils.toString(response.getEntity(),"UTF-8");
 }
 } catch (IOException e) {
 e.printStackTrace();
 }finally {
 if (response != null){
 try {
 response.close();
 } catch (IOException e) {
 logger.error("response close() error info {}", e.getMessage());
 }
 }
 logger.info("poolstas {}", poolingHttpClientConnectionManager.getTotalStats());
 }
 return null;
 }
}

1.5、监控分析

  1. PoolStats poolStats = httpClientConnectionManager.getTotalStats();

getAvailable()被闲置的持久连接数

getLeased() 被追踪的持久连接的数量目前链接管理器被用来执行请求

getMax() 被允许的持久连接的最大数量

getPending() 得到的链接请求阻塞等待一个空闲连接的数量

最近发表
标签列表