http连接池配置及spring boot restTemplate配置http连接池
本文为博主原创,转载请注明出处:
项目中存在第三方系统之间的服务调用通信,且会进行频繁调用,由于很早之前实现的调用方式为每调用一次外部接口,就需要新建一个HttpClient 对象。由于频繁调用,会存在性能问题。
针对这种场景,进行优化,使用httpClient 连接池,避免重复频繁创建httpClient 造成性能问题。以下为简单实现的demo:
1. 对 httpClient 的属性及常用配置封装 HttpPoolProperties
package com.example.demo.config; import lombok.Data;
import org.springframework.stereotype.Component; @Component
//@ConfigurationProperties(prefix = "http.pool.conn") // 可在配置文件中进行配置
@Data
public class HttpPoolProperties {
// 最大连接数
private Integer maxTotal = 20;
// 同路由并发数
private Integer defaultMaxPerRoute =20 ;
private Integer connectTimeout = 2000;
private Integer connectionRequestTimeout=2000;
private Integer socketTimeout= 2000;
// 线程空闲多久后进行校验
private Integer validateAfterInactivity= 2000;
// 重试次数
private Integer retryTimes = 2; // 是否开启充实
private boolean enableRetry = true;
// 重试的间隔:可实现 ServiceUnavailableRetryStrategy 接口
private Integer retryInterval= 2000;
}
2. 创建httpClient 连接池,并对RestTemplate 指定httpClient 及连接池
package com.example.demo.util; import com.example.demo.config.HttpPoolProperties;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
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.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate; @Configuration
public class HttpClientPoolUtils { @Autowired
private HttpPoolProperties httpPoolProperties; /**
* 首先实例化一个连接池管理器,设置最大连接数、并发连接数
* @return
*/
@Bean(name = "httpClientConnectionManager")
public PoolingHttpClientConnectionManager getHttpClientConnectionManager(){
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSocketFactory())
.build(); PoolingHttpClientConnectionManager httpClientConnectionManager = new PoolingHttpClientConnectionManager(registry);
//最大连接数
httpClientConnectionManager.setMaxTotal(httpPoolProperties.getMaxTotal());
//并发数
httpClientConnectionManager.setDefaultMaxPerRoute(httpPoolProperties.getDefaultMaxPerRoute()); httpClientConnectionManager.setValidateAfterInactivity(httpPoolProperties.getValidateAfterInactivity()); return httpClientConnectionManager;
} /**
* 实例化连接池,设置连接池管理器。
* 这里需要以参数形式注入上面实例化的连接池管理器
* @param httpClientConnectionManager
* @return
*/
@Bean(name = "httpClientBuilder")
public HttpClientBuilder getHttpClientBuilder(@Qualifier("httpClientConnectionManager")PoolingHttpClientConnectionManager httpClientConnectionManager){ //HttpClientBuilder中的构造方法被protected修饰,所以这里不能直接使用new来实例化一个HttpClientBuilder,可以使用HttpClientBuilder提供的静态方法create()来获取HttpClientBuilder对象
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); httpClientBuilder.setConnectionManager(httpClientConnectionManager); if (httpPoolProperties.isEnableRetry()){
// 重试次数
httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(httpPoolProperties.getRetryTimes(), true));
// 若需要自定义http 的重试策略,可以重新实现ServiceUnavailableRetryStrategy 或 HttpRequestRetryHandler接口,比如对指定异常或制定状态码进行重试,并指定充实的次数。
}else {
httpClientBuilder.disableAutomaticRetries();
}
// 另外httpClientBuilder 可以设置长连接策略,dns解析器,代理,拦截器以及UserAgent等等。可根据业务需要进行实现 return httpClientBuilder;
} /* 注入连接池,用于获取httpClient
* @param httpClientBuilder
* @return
*/
@Bean("httpClient")
public CloseableHttpClient httpClient(@Qualifier("httpClientBuilder") HttpClientBuilder httpClientBuilder){
return httpClientBuilder.build();
} /**
* Builder是RequestConfig的一个内部类
* 通过RequestConfig的custom方法来获取到一个Builder对象
* 设置builder的连接信息
* 这里还可以设置proxy,cookieSpec等属性。有需要的话可以在此设置
* @return
*/
@Bean(name = "builder")
public RequestConfig.Builder getBuilder(){
RequestConfig.Builder builder = RequestConfig.custom();
return builder.setConnectTimeout(httpPoolProperties.getConnectTimeout()) //连接上服务器(握手成功)的时间,超出抛出connect timeout
//从连接池中获取连接的超时时间,超时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
.setConnectionRequestTimeout(httpPoolProperties.getConnectionRequestTimeout())
//服务器返回数据(response)的时间,超过抛出read timeout
.setSocketTimeout(httpPoolProperties.getSocketTimeout());
} /**
* 使用builder构建一个RequestConfig对象
* @param builder
* @return
*/
@Bean
public RequestConfig getRequestConfig(@Qualifier("builder") RequestConfig.Builder builder){
return builder.build();
} /**
* RestTemplate 指定httpClient 及连接池
*
* @param httpClient
* @return
*/
@Bean(name = "httpClientTemplate")
public RestTemplate restTemplate(@Qualifier("httpClient") CloseableHttpClient httpClient) {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setHttpClient(httpClient);
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(factory);
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
return restTemplate;
} }
3。 创建清理线程对httpClient 空闲线程,失效线程进行清理
package com.example.demo.util; import org.apache.http.conn.HttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; @Component
public class IdleConnectionEvictor extends Thread {
@Autowired
private HttpClientConnectionManager connMgr; private volatile boolean shutdown; public IdleConnectionEvictor() {
super();
super.start();
} @Override
public void run() {
try {
while (!shutdown) {
synchronized (this) {
wait(5000);
// 关闭失效的连接
connMgr.closeExpiredConnections();
}
}
} catch (InterruptedException ex) {
// 结束
}
} //关闭清理无效连接的线程
public void shutdown() {
shutdown = true;
synchronized (this) {
notifyAll();
}
}
}
4. 单元测试
package com.example.demo; import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.web.client.RestTemplate; import java.io.IOException; @Slf4j
@SpringBootTest
public class HttpTest { @Autowired
private RestTemplate httpClientTemplate; @Autowired
private CloseableHttpClient httpClient; @Test
void test() throws IOException {
String result = httpClientTemplate.getForObject("https://www.baidu.com/",String.class);
System.out.println("httpClientTemplate==="+result);
// 声明 http get 请求
String url = "https://www.baidu.com/";
HttpGet httpGet = new HttpGet(url);
// 发起请求
CloseableHttpResponse response = this.httpClient.execute(httpGet);
System.out.println("httpClient==="+response);
} }
测试方法分别通过CloseableHttpClient httpClient 进行http调用与自定义的RestTemplate httpClientTemplate 进行 http 调用。
执行结果如下:
http连接池配置及spring boot restTemplate配置http连接池的更多相关文章
- Spring boot --- 自动配置
spring boot 自动配置 指的是针对很多spring 应用程序常见的应用功能,spring boot 能自动提供相关配置. spring boot 自动配置加载 Spring boot ...
- Spring Boot Security配置教程
1.简介 在本文中,我们将了解Spring Boot对spring Security的支持. 简而言之,我们将专注于默认Security配置以及如何在需要时禁用或自定义它. 2.默认Security设 ...
- Spring Boot自定义配置与加载
Spring Boot自定义配置与加载 application.properties主要用来配置数据库连接.日志相关配置等.除了这些配置内容之外,还可以自定义一些配置项,如: my.config.ms ...
- Spring Boot常用配置
概述 本文主要写了下Spring Boot的一些常用配置. Spring Boot基本配置 入口类: Spring Boot通常有一个名为*Application的入口类,入口类里面有一个main方法 ...
- Spring Boot 自动配置的原理、核心注解以及利用自动配置实现了自定义 Starter 组件
本章内容 自定义属性快速入门 外化配置 自动配置 自定义创建 Starter 组件 摘录:读书是读完这些文字还要好好用心去想想,写书也一样,做任何事也一样 图 2 第二章目录结构图 第 2 章 Spr ...
- 在 Spring Boot 中使用 HikariCP 连接池
上次帮小王解决了如何在 Spring Boot 中使用 JDBC 连接 MySQL 后,我就一直在等,等他问我第三个问题,比如说如何在 Spring Boot 中使用 HikariCP 连接池.但我等 ...
- Spring Boot + Mybatis 配置多数据源
Spring Boot + Mybatis 配置多数据源 Mybatis拦截器,字段名大写转小写 package com.sgcc.tysj.s.common.mybatis; import java ...
- spring boot 环境配置(profile)切换
Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...
- Spring Boot自动配置原理
使用Spring Boot之后,一个整合了SpringMVC的WEB工程开发,变的无比简单,那些繁杂的配置都消失不见了,这 是如何做到的? 一切魔力的开始,都是从我们的main函数来的,所以我们再次来 ...
- Sping Boot入门到实战之入门篇(四):Spring Boot自动化配置
该篇为Sping Boot入门到实战系列入门篇的第四篇.介绍Spring Boot自动化配置的基本原理与实现. Spring Boot之所以受开发者欢迎, 其中最重要的一个因素就是其自动化配置特性 ...
随机推荐
- linux 上安装kapacitor
转载请注明出处: 1.通过安装包安装 1.使用以下命令下载安装包: wget https://dl.influxdata.com/kapacitor/releases/kapacitor_1.6.3- ...
- spring是否线程安全
spring 管理的bean默认是单例的,可通过 scope 属性设置scope="singleton" 默认是单例,可修改为scope="prototype" ...
- HTML之元素相对页面(视口)左上角的绝对坐标
目录 一. 绝对位置 二. 相对位置 一. 绝对位置 网页元素的绝对位置,指该元素的左上角相对于整张网页左上角的坐标.无论网页滚动条如何滚动,它都是不会变化的. // 获取元素的绝对位置坐标(相对于页 ...
- Ubuntu 终端如何分割多个窗口
sudo apt-get install terminator 查看 ~/.config(隐藏文件夹 ctrl + h 即可看见) 下是否有 terminator 文件夹 如果没有手动创建一个 然后在 ...
- 目标检测 | Point Cloud RoI Pooling
目录 目标检测 | Point Cloud RoI Pooling Point Cloud RoI Pooling 概述 Pooling RoI Pooling Point Cloud RoI Poo ...
- 5分钟体验代码仓托管、CloudIDE云端代码编辑、调试、运行
摘要:您将学会如何通过代码托管(CodeHub)创建代码仓,解决软件开发者在跨地域协同.多分支并发.代码版本管理.安全性等方面的问题. 本文分享自华为云社区<5分钟体验代码仓托管.CloudID ...
- 华为云NFT云宝限量开抢,区块链技术为你的数字资产保驾护航
摘要:正是有这些底层的区块链技术支撑,才能让我们真正的"拥有"独属于自己的NFT数字资产. 本文分享自华为云社区<华为云独家NFT限量开抢,背后的这些技术你都知道吗?> ...
- 基于MRS-Hudi构建数据湖的典型应用场景介绍
摘要:华为云FunsionInsight MRS已集成Apache Hudi 0.8版本,基于MRS-Hudi构建数据湖解决方案. 本文分享自华为云社区<基于MRS-Hudi构建数据湖的典型应用 ...
- 一文带你从零认识什么是XLA
摘要:简要介绍XLA的工作原理以及它在 Pytorch下的使用. 本文分享自华为云社区<XLA优化原理简介>,作者: 拓荒者01. 初识XLA XLA的全称是Accelerated Lin ...
- docker镜像列表存在但删除显示 No such image问题解决
近期使用了docker,但删除镜像时候遇到了无法删除问题.提示:No such Image.原因有两个,解决方法如下: 原因1: 容器还存在是无法删除镜像的 解决步骤: 1.停掉容器(docker s ...