背景:最近工作上搭建了一个中间系统,采用了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. Strust2总结

    1. JavaEE软件三层结构和MVC的区别? JavaEE软件三层机构是由sun公司提供JavaEE开发规范的:Web层(表现层).业务逻辑层.数据持久层.[其中WEB层会使用前端控制器模式] MV ...

  2. Django(ORM常用字段)

    day68 参考:http://www.cnblogs.com/liwenzhou/p/8688919.html 1. Django ORM常用字段:             1. AutoField ...

  3. SpringMvc 启动原理源码分析

    了解一个项目启动如何实现是了解一个框架底层实现的一个必不可少的环节.从使用步骤来看,我们一般是引入包之后,配置web.xml文件.官方文档示例的配置如下: <web-app> <se ...

  4. SpringBoot配置文件application.properties详解

    喜欢的朋友可以关注下,粉丝也缺. 相信很多的码友在接触springboot时,不知道怎么去配置一些项目中需要的配置,比如数据源,tomcat调优,端口等等,下面我就给大家奉献出一些项目中常用的配置信息 ...

  5. Mxonline3.6 在阿里云服务器上的部署(uwsgi nginx)

    我的项目结构 1. 执行`python manage.py migrate`命令,将迁移文件,映射到数据库中,创建相应的表. 进入数据库 use mxonline数据库     source /hom ...

  6. String、StringBuffer与StringBuilder之间区别 (转载)

    最近学习到StringBuffer,心中有好些疑问,搜索了一些关于String,StringBuffer,StringBuilder的东西,现在整理一下. 关于这三个类在字符串处理中的位置不言而喻,那 ...

  7. 常见数据结构的Java实现

    单链表的Java实现 首先参考wiki上的单链表说明,单链表每个节点包含数据和指向链表中下一个节点的指针或引用.然后看代码 import java.lang.*; public class Singl ...

  8. wordpress添加文章阅读数量

    将下面代码添加到functions.php //取得文章的阅读次数 function post_views($before = '点击 ', $after = ' 次', $echo = 1) { g ...

  9. “声讨”高云的《jQuery技术内幕》

    1. 前言: 其实本文有点太标题党了,哈哈,见谅.说“声讨”,就是说说我作为一个<jQuery技术内幕>一个忠实读者,读本书的一些想法和建议. 2014年2月20日,我收到了<jQu ...

  10. CentOS7安装sogou输入法

    centos7中自带的ibus用起来相当不爽,就决定自己换个搜狗,遇到阻力不少,在此记下,防止下次不会也给大家提供一些参考.(参见<kali下安装中文输入法>) 准备阶段: 安装fcitx ...