配置
connectionRequestTimeout :从连接池中获取可用连接的时间
connectTimeout :连接超时时间,客户端请求服务器与服务器建立连接(三次握手)成功的最大接受时间
socketTimeout :请求获取数据的超时时间,访问一个接口指定时间内无法返回数据,直接放弃此次调用
MaxtTotal是整个池子的大小
DefaultMaxPerRoute是根据连接到的主机对MaxTotal的一个细分,默认是2
//http client的重试次数,默认是3次
setHttpRequestRetryHandler
#提交请求前测试连接是否可用
http.staleConnectionCheckEnabled=true
#连接池的最大连接数,0代表不限;如果取0,需要考虑连接泄露导致系统崩溃的后果
http-client.pool.maxTotal=1000
#每个路由的最大连接数,如果只调用一个地址,可以将其设置为最大连接数
http-client.pool.defaultMaxPerRoute=200
#空闲多长时间(毫秒)来校验连接的有效性
http-client.pool.validateAfterInactivity=2000
#指客户端和服务器建立连接的超时时间 (ms)
#最大约21秒,因为内部tcp在进行三次握手建立连接时,默认tcp超时时间是20秒,即便设置100s也是在21s后报错.
http-client.pool.connectTimeout=3000
#指客户端从服务器读取数据包的间隔超时时间,不是总读取时间,也就是socket timeout,ms
http-client.pool.socketTimeout=5000
#从连接池获取连接的timeout,不宜过大,ms
http-client.pool.connectionRequestTimout=200
#重试次数
http-client.pool.retryTimes=5
http-client.pool.charset=UTF-8
#若是少数固定客户端,长时间高频次的访问服务器,启用keep-alive非常合适!
#长连接保持时间 单位s,不宜过长
http-client.pool.keepAliveTime=10
#针对项目的特定业务(拆分Excel)保持长连接时间(单位:s)
http-client.pool.splitAliURLKeepAliveTime=30
#长连接内最多请求次数
#在keepAliveTime时间内每来一个新的请求,keepAliveTimeMaxConn会自动减1,直到为0,强制断掉连接
#http-client.pool.keepAliveTimeMaxConn=1000
#客户端在发送Request Message之前,先判断服务器是否愿意接受客户端发送的消息主体
http-client.pool.expectContinueEnabled=false
#定义连接管理器将由多个客户端实例共享。
#如果连接管理器是共享的,则其生命周期应由调用者管理,如果客户端关闭则不会关闭。
http-client.pool.connectionManagerShared=true
MyHttpClientConfig
@Data
@ConfigurationProperties(prefix="http-client.pool")
@Component
public class MyHttpClientProperties {
private int maxTotal;
private int defaultMaxPerRoute;
private int connectTimeout;
private int socketTimeout;
private int connectionRequestTimout;
private int retryTimes;
private String charset;
private int keepAliveTime;
private int validateAfterInactivity;
private int splitAliURLKeepAliveTime;
private Boolean expectContinueEnabled;
private Boolean connectionManagerShared;
}
@Configuration
public class MyHttpClientConfig {
private static final String MY_COOKIE_EASY = "easy";
@Autowired
private MyHttpClientProperties hp;
@Bean
public PoolingHttpClientConnectionManager poolingHttpClientConnectionManager() {
PoolingHttpClientConnectionManager phccm = new PoolingHttpClientConnectionManager();
phccm.setMaxTotal(hp.getMaxTotal());
phccm.setDefaultMaxPerRoute(hp.getDefaultMaxPerRoute());
phccm.setValidateAfterInactivity(hp.getValidateAfterInactivity());
return phccm;
}
public CookieSpecProvider easyCookieSpecProvider() {
return new CookieSpecProvider() {
@Override
public CookieSpec create(HttpContext context) {
return new DefaultCookieSpec() {
@Override
public void validate(Cookie cookie, CookieOrigin origin) throws MalformedCookieException {
}
};
}
};
}
public Registry<CookieSpecProvider> myCookieSpecProvider() {
PublicSuffixMatcher publicSuffixMatcher = PublicSuffixMatcherLoader.getDefault();
Registry<CookieSpecProvider> cs = RegistryBuilder.<CookieSpecProvider>create()
.register(CookieSpecs.DEFAULT, new DefaultCookieSpecProvider(publicSuffixMatcher))
.register(CookieSpecs.STANDARD,new RFC6265CookieSpecProvider(publicSuffixMatcher))
.register(MY_COOKIE_EASY, easyCookieSpecProvider())
.build();
return cs;
}
@Bean
public RequestConfig requestConfig() {
return RequestConfig.custom()
.setConnectionRequestTimeout(hp.getConnectionRequestTimout())
.setConnectTimeout(hp.getConnectTimeout())
.setSocketTimeout(hp.getSocketTimeout())
.setExpectContinueEnabled(hp.getExpectContinueEnabled())
.setCookieSpec(MY_COOKIE_EASY)
.build();
}
public ConnectionKeepAliveStrategy myStrategy() {
return new ConnectionKeepAliveStrategy() {
@Override
public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE));
while(it.hasNext()) {
HeaderElement he = it.nextElement();
String param = he.getName();
String value = he.getValue();
if(value!=null && param.equalsIgnoreCase(MyConstant.TIMEOUT)) {
try {
return Long.parseLong(value)*MyConstant.THOUSAND;
} catch (Exception e) {
e.printStackTrace();
}
}
}
HttpHost target = (HttpHost) context.getAttribute(HttpClientContext.HTTP_TARGET_HOST);
if(MyConstant.ALI_URL_HOST.equalsIgnoreCase(target.getHostName())) {
return hp.getSplitAliURLKeepAliveTime()*MyConstant.THOUSAND;
}
return hp.getKeepAliveTime()*MyConstant.THOUSAND;
}
};
}
public HttpRequestRetryHandler myRetry() {
return new HttpRequestRetryHandler() {
@Override
public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
if (executionCount >= hp.getRetryTimes()) {
return false;
}
if (exception instanceof NoHttpResponseException) {
return true;
}
if (exception instanceof SSLHandshakeException) {
return false;
}
if (exception instanceof InterruptedIOException) {
return false;
}
if (exception instanceof UnknownHostException) {
return false;
}
if (exception instanceof ConnectTimeoutException) {
return false;
}
if (exception instanceof SSLException) {
return false;
}
HttpClientContext clientContext = HttpClientContext
.adapt(context);
HttpRequest request = clientContext.getRequest();
if (!(request instanceof HttpEntityEnclosingRequest)) {
return true;
}
return false;
}
};
}
@Bean
public HttpClientBuilder httpClientBuilder(PoolingHttpClientConnectionManager phccm) {
HttpClientBuilder hb = HttpClientBuilder.create();
hb.setConnectionManager(phccm);
hb.setDefaultCookieSpecRegistry(myCookieSpecProvider());
hb.setDefaultRequestConfig(requestConfig());
hb.setConnectionManagerShared(hp.getConnectionManagerShared());
hb.setKeepAliveStrategy(myStrategy());
hb.setRetryHandler(myRetry());
return hb;
}
@Bean
public CloseableHttpClient getCloseableHttpClient(HttpClientBuilder hb) {
return hb.build();
}
}