如果每次都重新创建一个新的HttpClient对象的话,当并发上来时,容易出现异常或连接失败,超时。这里可以使用HttpClient的连接池配置,减少HttpClient创建的数量,减少资源开销。
package
com.mygame.common.utils;
import
java.io.IOException;
import
java.security.KeyManagementException;
import
java.security.KeyStoreException;
import
java.security.NoSuchAlgorithmException;
import
org.apache.http.Header;
import
org.apache.http.HttpStatus;
import
org.apache.http.client.config.RequestConfig;
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.config.Registry;
import
org.apache.http.config.RegistryBuilder;
import
org.apache.http.conn.socket.ConnectionSocketFactory;
import
org.apache.http.conn.socket.PlainConnectionSocketFactory;
import
org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import
org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import
org.apache.http.entity.StringEntity;
import
org.apache.http.impl.client.CloseableHttpClient;
import
org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import
org.apache.http.impl.client.HttpClients;
import
org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import
org.apache.http.ssl.SSLContextBuilder;
import
org.apache.http.util.EntityUtils;
import
org.slf4j.Logger;
import
org.slf4j.LoggerFactory;
import
com.alibaba.fastjson.JSON;
public
class
GameHttpClient {
private
static
Logger logger = LoggerFactory.getLogger(GameHttpClient.
class
);
// 池化管理
private
static
PoolingHttpClientConnectionManager poolConnManager =
null
;
private
static
CloseableHttpClient httpClient;
// 它是线程安全的,所有的线程都可以使用它一起发送http请求
static
{
try
{
System.out.println(
"初始化HttpClientTest~~~开始"
);
SSLContextBuilder builder =
new
SSLContextBuilder();
builder.loadTrustMaterial(
null
,
new
TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslsf =
new
SSLConnectionSocketFactory(builder.build());
// 配置同时支持 HTTP 和 HTPPS
Registry
"http"
, PlainConnectionSocketFactory.getSocketFactory()).register(
"https"
, sslsf).build();
// 初始化连接管理器
poolConnManager =
new
PoolingHttpClientConnectionManager(socketFactoryRegistry);
poolConnManager.setMaxTotal(
640
);
// 同时最多连接数
// 设置最大路由
poolConnManager.setDefaultMaxPerRoute(
320
);
// 此处解释下MaxtTotal和DefaultMaxPerRoute的区别:
// 1、MaxtTotal是整个池子的大小;
// 2、DefaultMaxPerRoute是根据连接到的主机对MaxTotal的一个细分;比如:
// MaxtTotal=400 DefaultMaxPerRoute=200
// 而我只连接到http://www.abc.com时,到这个主机的并发最多只有200;而不是400;
// 而我连接到http://www.bac.com 和
// http://www.ccd.com时,到每个主机的并发最多只有200;即加起来是400(但不能超过400);所以起作用的设置是DefaultMaxPerRoute
// 初始化httpClient
httpClient = getConnection();
System.out.println(
"初始化HttpClientTest~~~结束"
);
}
catch
(NoSuchAlgorithmException e) {
e.printStackTrace();
}
catch
(KeyStoreException e) {
e.printStackTrace();
}
catch
(KeyManagementException e) {
e.printStackTrace();
}
}
public
static
CloseableHttpClient getConnection() {
RequestConfig config = RequestConfig.custom().setConnectTimeout(
5000
).setConnectionRequestTimeout(
5000
).setSocketTimeout(
5000
).build();
CloseableHttpClient httpClient = HttpClients.custom()
// 设置连接池管理
.setConnectionManager(poolConnManager)
.setDefaultRequestConfig(config)
// 设置重试次数
.setRetryHandler(
new
DefaultHttpRequestRetryHandler(
2
,
false
)).build();
return
httpClient;
}
public
static
String httpGet(String url) {
HttpGet httpGet =
new
HttpGet(url);
CloseableHttpResponse response =
null
;
try
{
response = httpClient.execute(httpGet);
String result = EntityUtils.toString(response.getEntity());
int
code = response.getStatusLine().getStatusCode();
if
(code == HttpStatus.SC_OK) {
return
result;
}
else
{
logger.error(
"请求{}返回错误码:{},{}"
, url, code,result);
return
null
;
}
}
catch
(IOException e) {
logger.error(
"http请求异常,{}"
,url,e);
}
finally
{
try
{
if
(response !=
null
)
response.close();
}
catch
(IOException e) {
e.printStackTrace();
}
}
return
null
;
}
public
static
String post(String uri, Object params, Header... heads) {
HttpPost httpPost =
new
HttpPost(uri);
CloseableHttpResponse response =
null
;
try
{
StringEntity paramEntity =
new
StringEntity(JSON.toJSONString(params));
paramEntity.setContentEncoding(
"UTF-8"
);
paramEntity.setContentType(
"application/json"
);
httpPost.setEntity(paramEntity);
if
(heads !=
null
) {
httpPost.setHeaders(heads);
}
response = httpClient.execute(httpPost);
int
code = response.getStatusLine().getStatusCode();
String result = EntityUtils.toString(response.getEntity());
if
(code == HttpStatus.SC_OK) {
return
result;
}
else
{
logger.error(
"请求{}返回错误码:{},请求参数:{},{}"
, uri, code, params,result);
return
null
;
}
}
catch
(IOException e) {
logger.error(
"收集服务配置http请求异常"
, e);
}
finally
{
try
{
if
(response !=
null
) {
response.close();
}
}
catch
(IOException e) {
e.printStackTrace();
}
}
return
null
;
}
}