HttpClientFactory
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.http.*;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.UnknownHostException;
public class HttpClientFactory {
public static HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() {
@Override
public boolean retryRequest(IOException exception,
int executionCount, HttpContext context) {
if (executionCount >= 5) {
return false;
}
if (exception instanceof NoHttpResponseException) {
return true;
}
if (exception instanceof InterruptedIOException) {
return false;
}
if (exception instanceof UnknownHostException) {
return false;
}
if (exception instanceof ConnectTimeoutException) {
return false;
}
HttpClientContext clientContext = HttpClientContext
.adapt(context);
HttpRequest request = clientContext.getRequest();
return !(request instanceof HttpEntityEnclosingRequest);
}
};
private static final int MAX_TOTAL_CONNECTIONS = 1000;
private static final int MAX_CONNECTIONS_PER_ROUTE = 600;
private static final int CONNECTION_TIMEOUT_MS = 10000;
private static final int SOCKET_TIMEOUT_MS = 30000;
private static ConnectionKeepAliveStrategy connectionKeepAliveStrategy;
public static ClientInstance create(HttpHost proxy) {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(MAX_TOTAL_CONNECTIONS);
connectionManager.setDefaultMaxPerRoute(MAX_CONNECTIONS_PER_ROUTE);
ConnectionKeepAliveStrategy strategy;
if (connectionKeepAliveStrategy != null) {
strategy = connectionKeepAliveStrategy;
} else {
strategy = getConnectionKeepAliveStrategy();
}
HttpClient httpClient;
httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.setKeepAliveStrategy(strategy)
.setRetryHandler(httpRequestRetryHandler)
.setDefaultRequestConfig(createRequestConfig())
.setProxy(proxy)
.build();
Thread daemonThread = new Thread(new IdleConnectionMonitorThread(connectionManager));
daemonThread.setDaemon(true);
daemonThread.start();
return new ClientInstance(httpClient, daemonThread);
}
public static ConnectionKeepAliveStrategy getConnectionKeepAliveStrategy() {
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
("timeout")) {
return Long.parseLong(value) * 1000;
}
}
return 60 * 1000;//如果没有约定,则默认定义时长为60s
}
};
}
public static void setConnectionKeepAliveStrategy(ConnectionKeepAliveStrategy connectionKeepAliveStrategy) {
HttpClientFactory.connectionKeepAliveStrategy = connectionKeepAliveStrategy;
}
private static RequestConfig createRequestConfig() {
return RequestConfig.custom()
.setConnectTimeout(CONNECTION_TIMEOUT_MS) //连接超时时间
.setSocketTimeout(SOCKET_TIMEOUT_MS) //socket超时时间
.setConnectionRequestTimeout(CONNECTION_TIMEOUT_MS) //从连接池获取连接的超时时间
.setExpectContinueEnabled(false) //禁用"Expect: 100-continue"头
.setStaleConnectionCheckEnabled(true) //开启stale connection检查
//.setProxy(new HttpHost("proxy.example.com", 8080)) //设置代理服务器地址和端口号,这个参数可以根据实际情况进行设置。如果不需要使用代理服务器,可以将这一行代码删除或注释掉。
.build();
}
@Getter
@AllArgsConstructor
public static class ClientInstance{
private HttpClient httpClient;
private Thread daemonThread;
}
}
IdleConnectionMonitorThread
import org.apache.http.conn.HttpClientConnectionManager;
import java.util.concurrent.TimeUnit;
public class IdleConnectionMonitorThread extends Thread {
private final HttpClientConnectionManager connMgr;
private volatile boolean shutdown;
public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr) {
super();
this.connMgr = connMgr;
}
@Override
public void run() {
try {
while (!shutdown) {
synchronized (this) {
wait(5000);
// Close expired connections
connMgr.closeExpiredConnections();
// Optionally, close connections
// that have been idle longer than 30 sec
connMgr.closeIdleConnections(30, TimeUnit.SECONDS);
}
}
} catch (InterruptedException ex) {
// terminate
}
}
public void shutdown() {
shutdown = true;
synchronized (this) {
notifyAll();
}
}
}