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之所以受开发者欢迎, 其中最重要的一个因素就是其自动化配置特性 ...
随机推荐
- IDEA在new对象的时候不显示其parameter
问题现象 最近安装了一个IDEA2023.1版本,出现了new对象不显示相关构造参数 解决办法 在IDEA的设置中开启相关提示 勾选上面的几个设置,保存 效果
- 数据库系列:业内主流MySQL数据中间件梳理
数据库系列:MySQL慢查询分析和性能优化 数据库系列:MySQL索引优化总结(综合版) 数据库系列:高并发下的数据字段变更 数据库系列:覆盖索引和规避回表 数据库系列:数据库高可用及无损扩容 数据库 ...
- 华企盾DSC造成svn、git连接不上常见处理方法
1.检查svn服务器是否正在运行 2.检查个人模式连接不上服务器网络加密了客户端未加密(查看客户端日志进程是否为legal:1网络访问设置是否正常,试试只加密服务器IP及端口的方式),个人模式可以连接 ...
- python tkinter 使用(二)
python tkinter 使用(二) 本篇文章着重讲下tkinter中messagebox的使用. 1:提示框 def showinfo(event): messagebox.showinfo(& ...
- MinIO客户端之ping
MinIO提供了一个命令行程序mc用于协助用户完成日常的维护.管理类工作. 官方资料 mc ping 检查指定的MinIO节点的服务是否可用. 不带参数,命令如下: ./mc ping local1 ...
- 11 个步骤完美排查Linux服务器是否被入侵
文章来源公众号:LemonSec 随着开源产品的越来越盛行,作为一个Linux运维工程师,能够清晰地鉴别异常机器是否已经被入侵了显得至关重要,个人结合自己的工作经历,整理了几种常见的机器被黑情况供参考 ...
- 《An End-to-end Model for Entity-level Relation Extraction using Multi-instance Learning》阅读笔记
代码 原文地址 预备知识: 1.什么是MIL? 多示例学习(MIL)是一种机器学习的方法,它的特点是每个训练数据不是一个单独的实例,而是一个包含多个实例的集合(称为包).每个包有一个标签,但是 ...
- 遍历菜单树得到所有菜单ids
1.前言 在我们实现菜单管理页面的时候,有时候我们需要默认展开所有的菜单列表,但是因为后端有时候没有返回所有菜单ids数组. 而且我们也不容易获取到所有菜单ids,比如如果我们通过角色id查询到所有菜 ...
- Quartz.Net系列(五):Quartz五大构件Job之JobBuilder解析
所有方法图: 1.Create,OfType 在JobBuilder中有五种方法执行Action: var job1 = JobBuilder.Create().OfType<FirstJob& ...
- 理论+实践详解最热的LLM应用框架LangChain
本文分享自华为云社区<LangChain是什么?LangChain的详细介绍和使用场景>,作者:码上开花_Lancer . 一.概念介绍 1.1 Langchain 是什么? 官方定义是: ...