连接管理:
两个主机之间建立的过程是很复杂的,包括了两个终端之间许多数据包的交换,会消耗掉大量的时间。对于很小的HTTP报文传输,TCP/IP的握手环节也是必不可少的。如果已有的链接能够重复使用,来执行多个请求,将会加大程序的数据吞吐量。HttpClient完全地支持连接持久化。
连接池管理器 Pool Connection Manager:
PoolingHttpClientConnectionManager 是一个管理客户端连接更复杂的实现。它为执行多线程的连接请求提供服务。对于每个基本的路由,连接都是池管理的。对于路由的请求,连接器在池中有可用的持久性连接,
将被从池中取出连接服务,而不是创建一个新的连接。对每个基本路由,PoolingHttpClientConnectionManager保持着一个最大限制的连接数。使用HttpClient.close() 释放连接。
当使用PoolingClientConnectionManager 时可以使用多线程来同时执行多个请求。如果池中没有可用的连接,请求将会被阻塞,直到有可用的连接。如果在一定的时间内不能被响应,将会抛出ConnectionPoolTimeoutException异常。
代码示例:
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.BasicCookieStore;
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.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContexts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HttpClientUtils {
private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);
private final HttpClientContext context = new HttpClientContext(); // 初始化上下文实例
private final HttpClientConnectionManager manager = builderPoolConnectionManager(); // 定义连接池管理变量
private final String CHAR_SET = "UTF-8";
public HttpClientUtils() {
CookieStore cookieStore = new BasicCookieStore();
context.setCookieStore(cookieStore);
}
public HttpClientConnectionManager builderPoolConnectionManager() {
final SSLContext context = SSLContexts.createSystemDefault();
final HostnameVerifier verifier = new DefaultHostnameVerifier();
// 自定义注册器,既可以发送http请求,也可以发送https请求
final Registry<ConnectionSocketFactory> register = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", new SSLConnectionSocketFactory(context, verifier)).build();
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(
register);
poolingHttpClientConnectionManager.setMaxTotal(200); // 设置连接池的最大连接数
poolingHttpClientConnectionManager.setDefaultMaxPerRoute(poolingHttpClientConnectionManager.getMaxTotal()); // 一个路由的最大连接数
return poolingHttpClientConnectionManager;
}
public CloseableHttpClient buildHttpClient() {
RequestConfig config = RequestConfig.custom().setConnectionRequestTimeout(3000) // 从池中获取请求的时间
.setConnectTimeout(2000) // 连接到服务器的时间
.setSocketTimeout(5000).build(); // 读取信息时间
// 如果使用了代理,请打开注释
// HttpHost proxy = new HttpHost("127.0.0.1" , 2924) ;
// HttpRoutePlanner httpRoutePlanner = new HttpRoutePlanner() {
// @Override
// public HttpRoute determineRoute(HttpHost httpHost, HttpRequest httpRequest,
// HttpContext httpContext) throws HttpException {
// return new HttpRoute(httpHost ,proxy);
// }
// };
CloseableHttpClient build = HttpClients.custom().setRetryHandler(DefaultHttpRequestRetryHandler.INSTANCE)
.setDefaultRequestConfig(config).setConnectionManagerShared(true).setConnectionManager(manager)
// .setRoutePlanner(httpRoutePlanner) 设置路由
.build();
return build;
}
public String post(String url, Map<String, String> params) {
HttpPost post = new HttpPost(url);
String resp = null;
// 这里每次拿到的是池内的一个空闲连接,而不是新建 的连接
CloseableHttpClient httpClient = new HttpClientUtils().buildHttpClient();
try {
try {
if (params != null) {
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
for (Map.Entry<String, String> param : params.entrySet()) {
nvps.add(new BasicNameValuePair(param.getKey(), param.getValue()));
}
post.setEntity(new UrlEncodedFormEntity(nvps, CHAR_SET));
}
HttpResponse response = httpClient.execute(post);
InputStream input = response.getEntity().getContent();
resp = IOUtils.toString(input);
input.close();// 释放连接,以便下个请求复用
} catch (ClientProtocolException e) {
logger.error(e.getMessage(), e);
} catch (IOException e) {
logger.error(e.getMessage(), e);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
} finally {
if (post != null) {
post.releaseConnection();
}
}
return resp;
}
}
连接池使用注意事项:
1. 连接池中连接都是在发起请求的时候建立,并且都是长连接
2. HttpResponse input.close();作用就是将用完的连接释放,下次请求可以复用,这里特别注意的是,如果不使用in.close();而仅仅使用httpClient.close();结果就是连接会被关闭,并且不能被复用,这样就失去了采用连接池的意义。
3. 连接池释放连接的时候,并不会直接对TCP连接的状态有任何改变,只是维护了两个Set,leased和avaliabled,leased代表被占用的连接集合,avaliabled代表可用的连接的集合,释放连接的时候仅仅是将连接从leased中remove掉了,并把连接放到avaliabled集合中。
对RequestConfig里timeout的解释:
RequestConfig config = RequestConfig.custom()
.setConnectionRequestTimeout(3000) //从池中获取请求的时间
.setConnectTimeout(2000) //连接到服务器的时间
.setSocketTimeout(5000).build(); //读取信息时间
setConnectTimeout:设置连接超时时间,单位毫秒。ConnectTimeoutException
setConnectionRequestTimeout:设置从connect Manager获取Connection 超时时间,单位毫秒。这个属性是新加的属性,因为目前版本是可以共享连接池的。ConnectionPoolTimeout
setSocketTimeout:请求获取数据的超时时间,单位毫秒。 如果访问一个接口,多少时间内无法返回数据,就直接放弃此次调用。SocketTimeoutException
更详细的说明可以参考:
https://blog.csdn.net/ll641058431/article/details/79566277
相关推荐
HttpAsyncClient连接池的使用,项目中频繁发送http请求,同步http阻塞主线程,影响性能,使用 HttpAsyncClient可使性能提高,这里配合连接池使用,效果更好,同时还附带同步httpClient的连接池使用
HttpClient连接池是网络编程中一个重要的优化手段,它允许我们重用已经建立的HTTP连接,减少每次请求时的建立和关闭连接的开销,从而提高应用程序的性能和效率。Apache HttpClient库提供了这样的功能,让我们能够...
HTTPClient工具类,完整,HTTPClient工具类,完整,HTTPClient工具类,完整HTTPClient工具类,完整,HTTPClient工具类,完整
《连接池实现原理及效率测试》 连接池是数据库应用中的一个重要概念,它在系统设计中扮演着提高性能、优化资源利用的关键角色。本文将深入探讨连接池的实现原理,并通过实际测试分析其效率。 首先,我们需要理解...
在Spring Boot应用中,连接池是管理数据库连接的关键组件,它能提高数据库操作的效率和应用程序的性能。本文将深入探讨如何使用注解配置在Spring Boot中设置连接池。 首先,Spring Boot默认集成了多种数据库连接池...
4. **HttpClient连接池管理** - HttpClient默认使用长连接,Tomcat中,默认的最大长连接时间为`connectionTimeout`。 - 如果手动调用`releaseConnection`,在`ManagedClientConnectionImpl`中会关闭socket,而如果...
封装好的httpClient工具类里面包含了get 和 post两种请求
Httpclient连接池
静态初始化HttpClient和连接池管理器: ```java static { // 创建连接池管理器 cm = new PoolingHttpClientConnectionManager(); // 设置整个连接池的最大连接数 cm.setMaxTotal(200); // 设置每个路由上的默认...
HttpClient连接池 Spring依赖注入 lombok简化POJO开发 原子变量 内置锁 CompletionService log4j+slf4j日志 实现的功能 登录注销 单聊 群聊 客户端提交任务,下载图片并显示 上线下线公告 在线用户记录 批量下载豆瓣...
HttpClient连接池 Spring依赖注入 lombok简化POJO开发 原子变量 内置锁 CompletionService log4j+slf4j日志 实现的功能 登录注销 单聊 群聊 客户端提交任务,下载图片并显示 上线下线公告 在线用户记录 批量下载豆瓣...
两个主机建立连接的过程是很复杂的一个过程,涉及到多个数据包...一般情况下,普通使用HttpClient已经能满足我们的需求,不过有时候,在我们需要高并发大量的请求网络的时候,还是用“连接池”这样的概念能提升吞吐量。
HttpClient连接池 Spring依赖注入 lombok简化POJO开发 原子指标 内置锁 竣工服务 log4j+slf4j日志 实现的功能 登录注销 单聊 群聊 客户端提交任务,下载图片并显示 上线下线公告 在线用户记录 批量下载豆瓣电影的...
HttpClientUtil可能需要配置连接池的大小、超时时间等参数,以适应不同的应用场景。 综上所述,HttpClientUtil工具类在IT应用中扮演着关键角色,简化了HTTP和HTTPS请求的实现,特别是发送文件这样的复杂操作。通过...
1. **连接管理**:HttpClient通过HttpConnectionManager接口控制HTTP连接的创建、复用和关闭,有效地管理连接池,避免了频繁建立新连接带来的性能开销。 2. **请求和响应模型**:HttpClient使用HttpRequest和...
HttpClient 3.1支持连接池,可以复用已建立的连接,提高性能。使用HttpConnectionManager来管理连接池,如SingleClientConnManager或MultiThreadedHttpConnectionManager。 五、重定向处理 HttpClient可以自动处理...
HttpClient 4.2.1是该项目的一个稳定版本,它包含了对HTTP协议的全面支持,包括基本的GET、POST请求,以及更复杂的重定向处理、Cookie管理、连接池等功能。 HttpClient 4.2.1版本引入了一些重要的改进和修复,以...
HttpClient 4.5提供了PoolingHttpClientConnectionManager,用于管理连接池。开发者可以设定最大连接数、每个路由的最大连接数,以及超时时间。连接池的使用可以显著减少建立新连接的开销,提高性能。 五、异步操作...
- HttpClient连接池 - Spring依赖注入 - lombok简化POJO开发 - 原子变量 - 内置锁 - CompletionService - log4j+slf4j日志 - 实现的功能 - 登录注销 - 单聊 - 群聊 - 客户端提交任务,下载图片并显示 -...