连接管理:
两个主机之间建立的过程是很复杂的,包括了两个终端之间许多数据包的交换,会消耗掉大量的时间。对于很小的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是java开发中非常常见的一种访问网络资源的方式了,下面这篇文章主要给大家介绍了关于Http持久连接和HttpClient连接池的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,...
springboot中注解配置连接池
NULL 博文链接:https://liujunhg.iteye.com/blog/1137411
封装好的httpClient工具类里面包含了get 和 post两种请求
实现httpClient连接池,同时支持http和https请求,代码可直接导入IDE运行,无冗余代码
Httpclient连接池
两个主机建立连接的过程是很复杂的一个过程,涉及到多个数据包...一般情况下,普通使用HttpClient已经能满足我们的需求,不过有时候,在我们需要高并发大量的请求网络的时候,还是用“连接池”这样的概念能提升吞吐量。
HttpClient连接池 Spring依赖注入 lombok简化POJO开发 原子指标 内置锁 竣工服务 log4j+slf4j日志 实现的功能 登录注销 单聊 群聊 客户端提交任务,下载图片并显示 上线下线公告 在线用户记录 批量下载豆瓣电影的...
主要介绍了使用java的HttpClient实现多线程并发的相关资料,需要的朋友可以参考下
- HttpClient连接池 - Spring依赖注入 - lombok简化POJO开发 - 原子变量 - 内置锁 - CompletionService - log4j+slf4j日志 - 实现的功能 - 登录注销 - 单聊 - 群聊 - 客户端提交任务,下载图片并显示 -...
12.2.2 HttpClient连接池源码分析 240 12.2.3 HttpClient 4.2.3配置 241 12.2.4 问题示例 243 12.3 线程池 244 12.3.1 Java线程池 245 12.3.2 Tomcat线程池配置 248 13 异步并发实战 250 13.1 同步阻塞调用 251 13.2...
HttpClientFactory(同步异步httpclient连接池工厂) http.sync HttpSyncClient(httpclient4.5.x封装) HttpSSLConnectionSocketFactory(https请求实现) HttpSSLConnectionSocketFactoryV2(https协议增加) ...
http连接池官方说明文档
Java基于多线程和NIO实现聊天室涉及到的技术点线程池ThreadPoolExecutor阻塞队列BlockingQueue,生产者消费者模式SelectorChannelByteBufferProtoStuff 高性能序列化HttpClient连接池Spring依赖注入lombok简化POJO...
连接池整合、跨域资源请求处理等。 项目结构 zhuozun ├ ├── zhuozun-admin-server -- 服务监控 | ├── zhuozun-api -- api接口,提供feign接口 | ├── zhuozun-cache-api -- 缓存接口api,提供feign接口 | ...
HttpClient接口调用工具类 (Post请求 get请求 put请求 delete请求 (附带调用demo) 下载就可以用 ) 可设置httpclient的连接池大小,连接池最大并发连接数,单路由最大并发数设
pool - 一个具有自主连接池和速率限制的HTTP客户端
httpclient获取目标网站内容,get、post方式(可运行),可以通过配置参数、配置连接池实现
没有使用框架,httpclient连接池+线程池+正则实现. 厚颜无耻的挂上博客+求波星 :) [removed]alert("XSS")[removed] [removed]alert(123)[removed] ´úÂë¹ýÂË£º medium--> ˫дÈÆ...