import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpRequestInterceptor; import org.apache.http.NoHttpResponseException; import org.apache.http.client.config.RequestConfig; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.config.SocketConfig; import org.apache.http.conn.DnsResolver; import org.apache.http.conn.HttpConnectionFactory; import org.apache.http.conn.ManagedHttpClientConnection; import org.apache.http.conn.routing.HttpRoute; 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.impl.DefaultConnectionReuseStrategy; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.DefaultHttpResponseParserFactory; import org.apache.http.impl.conn.ManagedHttpClientConnectionFactory; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.impl.conn.SystemDefaultDnsResolver; import org.apache.http.impl.io.DefaultHttpRequestWriterFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.io.IOException; import java.util.concurrent.TimeUnit; @Slf4j @Configuration public class HttpClientConfig { private static final Integer HTTP_CLIENT_VALIDATE_AFTER_INACTIVITY = 5 * 1000; private static final Integer HTTP_CLIENT_CONNECT_TIMEOUT = 10 * 1000; private static final Integer HTTP_CLIENT_SOCKET_TIMEOUT = 10 * 1000; private static final Integer HTTP_CLIENT_CONNECTION_REQUEST_TIMEOUT = 10 * 1000; private static final Integer HTTP_CLIENT_MAX_TOTAL = 500; private static final Integer HTTP_CLIENT_MAX_PER_ROUTE = 200; static PoolingHttpClientConnectionManager manager = null; private static CloseableHttpClient httpClient = null; static{ //注册访问协议相关Socket工厂 Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() .register("http", PlainConnectionSocketFactory.INSTANCE) .register("https", SSLConnectionSocketFactory.getSystemSocketFactory()) .build(); HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connectionFactory = new ManagedHttpClientConnectionFactory( DefaultHttpRequestWriterFactory.INSTANCE, DefaultHttpResponseParserFactory.INSTANCE); //DNS 解析器 DnsResolver dnsResolver = SystemDefaultDnsResolver.INSTANCE; //创建池化连接管理器 manager = new PoolingHttpClientConnectionManager(socketFactoryRegistry,connectionFactory,dnsResolver); //默认为Socket配置 SocketConfig defaultSocketConfig = SocketConfig.custom().setTcpNoDelay(true).build(); manager.setDefaultSocketConfig(defaultSocketConfig); //设置整个连接池的最大连接数 manager.setMaxTotal(HTTP_CLIENT_MAX_TOTAL); //每个路由的最大连接数 manager.setDefaultMaxPerRoute(HTTP_CLIENT_MAX_PER_ROUTE); //在从连接池获取连接时,连接不活跃多长时间后需要进行一次验证,默认2s manager.setValidateAfterInactivity(HTTP_CLIENT_VALIDATE_AFTER_INACTIVITY); //默认请求配置 RequestConfig defaultRequestConfig = RequestConfig.custom() //设置连接超时时间 .setConnectTimeout(HTTP_CLIENT_CONNECT_TIMEOUT) //设置等待数据超时时间 .setSocketTimeout(HTTP_CLIENT_SOCKET_TIMEOUT) //设置从连接池获取连接的等待超时时间 .setConnectionRequestTimeout(HTTP_CLIENT_CONNECTION_REQUEST_TIMEOUT) .build(); //创建HttpClient httpClient = HttpClients.custom() .setConnectionManager(manager) //连接池不是共享模式 .setConnectionManagerShared(false) //定期回收空闲连接 .evictIdleConnections(60, TimeUnit.SECONDS) //定期回收过期连接 .evictExpiredConnections() //连接存活时间,如果不设置,则根据长连接信息决定 .setConnectionTimeToLive(60, TimeUnit.SECONDS) //设置默认请求配置 .setDefaultRequestConfig(defaultRequestConfig) //连接重用策略,即是否能keepAlive .setConnectionReuseStrategy(DefaultConnectionReuseStrategy.INSTANCE) //长连接配置,即获取长连接生产多长时间 .setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE) //设置重试次数,默认是3次,当前是禁用掉(根据需要开启) .setRetryHandler(((e, i, httpContext) -> { if (i>3){ log.warn("Retry more than three times"); return false; } if (e instanceof NoHttpResponseException){ log.warn("NoHttpResponseException: on {} call,go on retry...", i); return true; } return false; })) .build(); //JVM停止或重启时,关闭连接池 释放连接 Runtime.getRuntime().addShutdownHook(new Thread(()->{ try { if (httpClient != null){ httpClient.close(); } } catch (IOException e) { log.error("error when close httpClient:{}", e); } })); } @Bean("commonHttpClient") public CloseableHttpClient getHttpClient(){ if (httpClient != null){ return HttpClientConfig.httpClient; } return null; }
参考博文:https://blog.csdn.net/lovomap151/article/details/78879904