背景:最近工作上搭建了一个中间系统,采用了RestTemplate框架调用第三系统restful接口,调用方采用轮询的方式调用本系统的相关接口,期间多次出现堆内存溢出,系统假死,通用java自带的java内存分析工具分析系统生成的dump文件发现有一对象一直没被回收,占用98%堆内存,使用MAT分析该对象所在的线程,发现是使用resttemplate的相关线程,及相关的线程产生的堆对象并没有随resttemplate的close后被清除掉,网上搜索相关资料显示,传统HttpClient 在高请求量和高并发情况,很容易出现堆内存溢出的情况,而使用Apache中的HttpClient的实例CloseableHttpClient很少发生该现象,而RestTemplate默认使用的是org.springframework.http.client.ClientHttpRequest,需在配置文件进行相关的替换;

本文主要记录springboot中配置RestTemplate。

1、添加依赖:

<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>

2、配置CloseableHttpClient向相关属性,并设置定时清理连接

Package com.**.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.HeaderElement;
import org.apache.http.HeaderElementIterator;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.connectionKeepAliveStrategy;
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.comn.ssl.TrustSelfsignedStrategy;
import org.apache.http.Impl.client.CloseableHttpClient;
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 org.apache.http.ssl.SSLContextBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeUnit; /* *
* Supports both HTTP and HTTPS
* Uses a connect ion pool to re-use connect ions and save overhead of creat ing connect ions.
* Has a custom connection keep-al ive strategy (to apply a default keep-alive if one isn't specified)
* starts an idle connection monitor to cont inuously clean up stale connections.
*/
@Slf4j
@Configuration
public class HttpClientConfig { //Determines the timeout in milliseconds until a connection is established.
private static final int CONNECT_TIMEOUT = 30000; //The timeout when requesting a connection from the connection manager.
private static final int REQUEST_ TIMEOUT = 30000; //The timeout for waiting for data
private static final int SOCKET_ TIMEOUT = 60000; private static final int MAX_ TOTAL CONNECTIONS = 50;
private static final int DEFAULT KEEP ALIVE_ TIME_ MIlLIS = 20 * 1000;
private static final int CLOSE_ IDLE_ CONNECTION WAIT_ TIME_ SECS = 30; @Bean
public PoolingHttpClientConnectionManager poolingConnectionManager() { SSLContextBuilder builder = new SSLContextBuilder ();
try {
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
}catch (NoSuchAlgorithmException | KeyStoreException e) {
log.error ("Pooling Connection Manager Initialisation failure because of"+ e.getMessage(), e);
}
SSLConnectionSocketFactory sslsf = null;
try{
sslsf = new SSLConnectionSocketFactory (builder.build());
} catch (KeyManagementException | NoSuchAlgorithmException e) {
log.error("Pooling Connection Manager Initialisation failure because of" + e.GetMessage(), e);
}
Registry <ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
.create ().register ("https", sslsf)
.register (id: "http", new PlainConnectionSocketFactory ())
.build (); PoolingHttpclientConnectionManager poolingConnectionManager = new PoolingHttpclientConnectionManager (socketFactoryRegistry);
poolingConnectionManager.setMaxTotal(MAX_ TOTAL CONNECTIONS);
return poolingConnectionManager;
} @Bean
public ConnectionKeepAliveStrategy connectionKeepAliveStrategy () {
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 DEFAULT_ KEEP_ALIVE_TIME_MILlIS;
}
};
}
@Bean
public CloseableHttpClient httpClient () {
RequestConfig requestConfig = RequestConfig.custom ()
.setConnectionRequestTimeout(REQUEST_TIMEOUT)
.setConnectTimeout (CONNECT_TIMEOUT)
.setSocketTimeout (SOCKET_TIMEOUT).build(); return Httpclients.custom ()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager (poolingConnectionManager ())
.setKeepAliveStrategy (connectionKeepAliveStrategy ())
.build ();
} @Bean
public Runnable idleConnectionMonitor (final PoolingHttpClientConnectionManager connectionManager){
return new Runnable() {
@override
@Scheduled(fixedDelay = 10000)
public void run() {
try {
if (connectionManager != null) {
log.trace("run IdleConnectionMonitor - Closing expired and idle connections... ");
connectionManager.closeExpiredConnections();
connectionManager.closeIdleConnections(CLOSE_IDLE_CONNECTION_WAIT_TIME_SECS, TimeUnit.SECONDS);
} else
log.info("run IdleConnectionMonitor - Http Client Connection manager is not initialised");
} catch (Exception e) {
log.error("run IdleConnectionMonitor - Exception occurred.msg={}. ", e.getMessage());
}
}
};
}
}

3、替换RestTemplate中的默认httpClient

Package com.**.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.Httpcomponentsclienthttprequestfactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.List; @Slf4j
@Configuration
public class RestTemplateConfig { @Autowired
CloseableHttpClient httpClient; @Bean
public RestTemplate restTemplate () { RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory()); /**
* StringHttpMessogeConverter 默认使用 IS0-8859-编码,此处修改为 UTF-8
*/
List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
Iterator<HttpMessageConverter<?>> iterator = messageConverters.iterator();
while (iterator.hasNext()) {
HttpMessageConverter<?> converter = iterator.next();
if (converter instanceof StringHttpMessageConverter) {
((StringHttpMessageConverter) converter).setDefaultCharset(Charset.forName("UTF-8"));
}
}
return restTemplate;
} @Bean
public HttpComponentsClientHttpRequestFactory clientHttpRequestfactory () {
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestfactory();
clientJttpRequestFactory.setHttpClient(httpClient);
return clientHttpRequestFactory;
} @Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setThreadNamePrefix("poolScheduler");
scheduler.setPoolSize (50);
return scheduler;
}
}

4、在启动类中注入RestTemplate类:

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder){
return builder.build();
}

至此,RestTemplate就可以正常使用了。

参考资料:https://www.cnblogs.com/jimw/p/9037542.html

SpingBoot —— RestTemplate的配置的更多相关文章

  1. RestTemplate

    RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率.调用RestTemplate的 ...

  2. 使用RestTemplate访问restful服务时遇到的问题

    可以通过通过wireshark抓包,使用Postman发送请求 wireshark是非常流行的网络封包分析软件,功能十分强大.可以截取各种网络封包,显示网络封包的详细信息.使用wireshark的人必 ...

  3. RestTemplate 微信接口 text/plain HttpMessageConverter

    一.背景介绍 使用 Spring Boot 写项目,需要用到微信接口获取用户信息. 在 Jessey 和 Spring RestTemplate 两个 Rest 客户端中,想到尽量不引入更多的东西,然 ...

  4. 如何使用RestTemplate访问restful服务

    一. 什么是RestTemplate 传统情况下在java代码里访问restful服务,一般使用Apache的HttpClient.不过此种方法使用起来太过繁琐.spring提供了一种简单便捷的模板类 ...

  5. springcloud配置需要主要的地方

    Eureka服务端 注册中心 <!-- Eureka服务端 --> <dependency> <groupId>org.springframework.cloud& ...

  6. Springboot 使用 RestTemplate

    每天学习一点点 编程PDF电子书.视频教程免费下载:http://www.shitanlife.com/code spring web 项目提供的RestTemplate,使java访问url更方便, ...

  7. (转载)spring RestTemplate用法详解

    前面介绍过spring的MVC结合不同的view显示不同的数据,如:结合json的view显示json.结合xml的view显示xml文档.那么这些数据除了在WebBrowser中用JavaScrip ...

  8. spring的RestTemplate使用指南

    前言:现在restful接口越来越广泛,而如今很多接口摒弃了传统的配置复杂的webService开发模式,在java领域只需要很简单的springMvc就可以声明为一个控制器,再加上service层, ...

  9. 使用RestTemplate时报错java.lang.IllegalStateException: No instances available for 127.0.0.1

    我在RestTemplate的配置类里使用了 @LoadBalanced@Componentpublic class RestTemplateConfig { @Bean @LoadBalanced ...

随机推荐

  1. 微服务 - Eureka注册中心

    我们来解决微服务的第一问题,服务的管理. 服务中心对外提供服务,需要对外暴露自己的地址.而consumer(调用者)需要记录服务提供者的地址.将来地址出现变更,还需要及时更新.这在服务较少的时候并不觉 ...

  2. 【062新题】OCP 12c 062出现大量新题-15

    choose one In your Oracle 12c database, you plan to execute the command: SQL> CREATE TABLESPACE t ...

  3. Python-实现图表绘制总结

    Numpy是Python开源的数值计算扩展,可用来存储和处理大型矩阵,比Python自身数据结构要高效: matplotlib是一个Python的图像框架,使用其绘制出来的图形效果和MATLAB下绘制 ...

  4. python 数据类型二 (列表和元组)

    一.列表 1.1 列表的介绍 列表是python的基本数据类型之一,其他编程语言也有类似的数据类型,比如JS中的数组,java中的数组等等,它是以[]括起来,每个元素用逗号隔开,而且可以存放各种数据类 ...

  5. Git-遇到的问题以及解决方法

    1.将本地内容推送到远程仓库后,远程仓库里的文件夹不可点击 原因:在本地添加文件夹A时,又在A里使用了git init命令 解决:删除文件夹A,再重新添加过 2.其他人推送不了内容到远程仓库 原因:权 ...

  6. css居中小结

    从css入门就开始接触,无所不在的,一直备受争议的居中问题. css居中分为水平居中和垂直居中,水平居中方式也较为常见和统一,垂直居中的方法就千奇百怪了. 博客原文地址:Claiyre的个人博客 ht ...

  7. Redis 入门知识

    Redis 的前世今生 Redis的诞生于2008年,由Salvatore Sanfilippo开发.最初作者在开发一个网站时,需要实现一个高性能的队列功能,在使用Mysql无果后,决定自己造一个轮子 ...

  8. ASM路径问题导致数据库不能正常启动 -- 报:ORA-03113: end-of-file on communication channel

    环境描述: 操作系统版本:Red Hat Enterprise Linux Server release 6.5 (Santiago) 数据库版本:Oracle 11.2.0.4 RAC 场景描述: ...

  9. system表空间空间不足解决办法

    场景描述: 系统表空间空间不足,导致应用无法正常连接!!! 环境描述: ORACLE 11G 查看当前表空间的整体使用情况,以及有没有开启自动扩展,以及扩展的最大限制!!! ---tablespace ...

  10. ES6 模块定义 export 与 import

    一般导出 export math.js export function* getFibo() { let a = 1; let b = 1; yield a; yield b; while (true ...