由于之前项目数据量小,直接用的一般的http请求,后边随着数据量猛增到百万级,造成大量http请求 org.apache.http.conn.ConnectTimeoutException ,上网搜了搜,大神们说原因是http请求过多,请求占资源一直没有释放,最后导致连接失败,看了下当时的http请求代码,的确没有释放的环节,当时也没有找需要再什么地方释放了,就整体改成连接池的模式,最后问题得以解决,下边直接贴代码
http请求格式枚举:
public enum FormatType {
xml(0,"text/xml"),
json(1,"text/json"),
appJson(2,"application/json");
FormatType(int num, String type) {
this.num = num;
this.formatType = type;
}
String formatType;
int num;
public int getNum() {
return num;
}
public String getFormatType() {
return formatType;
}
public static FormatType getFormatTypeByNum(int num) {
for(FormatType formatType : FormatType.values()){
if(num == formatType.num){
return formatType;
}
}
return null;
}
public void setFormatType(String formatType) {
this.formatType = formatType;
}
}
没有使用连接池http工具类:
public class HttpUtils {
private static Logger LOGGER = LoggerFactory.getLogger(HttpUtils.class);
private static int DEFAULT_SOCKET_TIMEOUT = 1000 * 61;
private static int DEFAULT_CONNECTION_REQUEST_TIMEOUT = 1000*61;
private static int DEFAULT_CONNECTION_TIMEOUT = 1000 * 120;//这个连接时间当时报错后以为是时间设置的短,就增加到2分钟了,改完也没用
public static String getXmlHttpsResponse(String url, String params, boolean isPost, FormatType format) {
return getXmlHttpsResponse(url, params, isPost, DEFAULT_SOCKET_TIMEOUT, DEFAULT_CONNECTION_REQUEST_TIMEOUT,DEFAULT_CONNECTION_TIMEOUT, format);
}
public static String getXmlHttpsResponse(String url, String params, boolean isPost, int socketTmeOut, int connectionRequestTimeOut, int connectionTimeOut, FormatType format) {
LOGGER.info("getXmlHttpsResponse params: url={} params={}", url, params);
String ret = "";
try {
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(connectionRequestTimeOut).setSocketTimeout(socketTmeOut).setConnectTimeout(connectionTimeOut).build();
CloseableHttpClient httpClient = createSSLClientDefault(url);
HttpRequestBase request = isPost ? new HttpPost(url) : new HttpGet(url);
if (isPost && params != null) {
StringEntity entity = new StringEntity(params, "UTF-8");
entity.setContentEncoding("UTF-8");
entity.setContentType(format.getFormatType());
((HttpPost) request).setEntity(entity);
}
request.setConfig(requestConfig);
HttpResponse response = httpClient.execute(request);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_OK) {
HttpEntity responseEntity = response.getEntity();
ret = EntityUtils.toString(responseEntity, "UTF-8");
} else {
LOGGER.error("getHttpResponse Error: StatusCode wrong,StatusLine={}", response.getStatusLine().toString());
}
} catch (Throwable e) {
LOGGER.error("getXmlHttpsResponse error", e);
}
return ret;
}
private static List<? extends NameValuePair> getNameValueParams(JSONObject jsonParams) {
List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
Iterator keys = jsonParams.keys();
while (keys.hasNext()) {
String key = (String) keys.next();
Object value = jsonParams.get(key);
String stringValue = "";
if (value instanceof String) {
stringValue = (String) value;
} else {
stringValue = String.valueOf(value);
}
params.add(new BasicNameValuePair(key, stringValue));
}
return params;
}
public static CloseableHttpClient createSSLClientDefault(String url) {
if (url != null && url.matches("https:.*?")) {
try {
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
/**
* 信任所有
*/
@Override
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
}).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
return HttpClients.custom().setSSLSocketFactory(sslsf).build();
} catch (KeyManagementException e) {
LOGGER.error("createSSLClientDefault Error:{}", e.getMessage());
} catch (NoSuchAlgorithmException e) {
LOGGER.error("createSSLClientDefault Error:{}", e.getMessage());
} catch (KeyStoreException e) {
LOGGER.error("createSSLClientDefault Error:{}", e.getMessage());
}
}
return HttpClients.custom().build();
}
/**
* 将map参数转化为url参数 Set<String> exclude 这个参数具体根据业务需求增加的,过滤某一个或者某几个字段不进行http参数构造
*/
public static String getUrlParam(Object param, Set<String> exclude) {
JSONObject jsonObject = JSONObject.fromObject(param);
LOGGER.info("json is " + jsonObject);
StringBuffer url = new StringBuffer();
// 组装参数
if (null != jsonObject) {
url.append("?");
for (Object key : jsonObject.keySet()) {
if (CollectionUtils.isNotEmpty(exclude) && exclude.contains(key.toString())) {
continue;
}
try {
url.append(key.toString() + "=" + URLEncoder.encode(jsonObject.get(key).toString(), "UTF-8") + "&");
} catch (Exception e) {
LOGGER.error("getUrlParam", e);
}
}
url.deleteCharAt(url.length() - 1);
}
return url.toString();
}
}
使用连接池的http工具类:
public class HttpPoolUtils {
private static final CloseableHttpClient httpClient;
public static final String CHARSET_UTF8 = "UTF-8";
// 将最大连接数增加到
public static final int MAX_TOTAL = 600;
// 将每个路由基础的连接增加到
public static final int MAX_ROUTE_TOTAL = 600;
public static final int SOCKET_TIME = 60 * 1000;
public static final int CONNECT_TIME = 60 * 1000;
public static final int CONNECTION_REQUEST_TIMEOUT = 60 * 1000;
private static Logger LOGGER = LoggerFactory.getLogger(HttpUtils.class);
static {
PoolingHttpClientConnectionManager httpClientConnectionManager = new PoolingHttpClientConnectionManager();
httpClientConnectionManager.setMaxTotal(MAX_TOTAL);
httpClientConnectionManager.setDefaultMaxPerRoute(MAX_ROUTE_TOTAL);
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT).setConnectTimeout(CONNECT_TIME).setSocketTimeout(SOCKET_TIME).build();
//设置重定向策略
LaxRedirectStrategy redirectStrategy = new LaxRedirectStrategy();
httpClient = HttpClients.custom().setConnectionManager(httpClientConnectionManager).setDefaultRequestConfig(requestConfig).setRedirectStrategy(redirectStrategy).build();
}
/**
params string类型,需要使用下边的 getUrlParam进行转换
isPost post or get
format 枚举类型 http请求具体的格式设置
*/
public static String getXmlHttpsResponse(String url, String params, boolean isPost, FormatType format) {
String ret = "";
HttpRequestBase request = isPost ? new HttpPost(url) : new HttpGet(url);
CloseableHttpResponse response = null;
try {
if (isPost && params != null) {
StringEntity entity = new StringEntity(params, CHARSET_UTF8);
entity.setContentEncoding(CHARSET_UTF8);
entity.setContentType(format.getFormatType());
((HttpPost) request).setEntity(entity);
}
response = httpClient.execute(request);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_OK) {
HttpEntity responseEntity = response.getEntity();
ret = EntityUtils.toString(responseEntity, CHARSET_UTF8);
EntityUtils.consume(responseEntity);
} else {
LOGGER.error("getHttpResponse Error: StatusCode wrong,StatusLine={}", response.getStatusLine().toString());
}
} catch (IOException e) {
LOGGER.error("getXmlHttpsResponse error", e);
} finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return ret;
}
/**
* 将map参数转化为url参数 Set<String> exclude 这个参数具体根据业务需求增加的,过滤某一个或者某几个字段不进行http参数构造
*/
public static String getUrlParam(Object param, Set<String> exclude) {
JSONObject jsonObject = JSONObject.fromObject(param);
LOGGER.info("json is " + jsonObject);
StringBuffer url = new StringBuffer();
// 组装参数
if (null != jsonObject) {
url.append("?");
for (Object key : jsonObject.keySet()) {
if (CollectionUtils.isNotEmpty(exclude) && exclude.contains(key.toString())) {
continue;
}
try {
url.append(key.toString() + "=" + URLEncoder.encode(jsonObject.get(key).toString(), "UTF-8") + "&");
} catch (Exception e) {
LOGGER.error("getUrlParam", e);
}
}
url.deleteCharAt(url.length() - 1);
}
return url.toString();
}
}