Le contenu de cet article concerne la méthode de configuration de RestTemplate dans Springboot. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.
Contexte : J'ai récemment construit un système intermédiaire au travail, en utilisant le framework RestTemplate pour appeler l'interface restful du troisième système. L'appelant a utilisé le sondage pour appeler les interfaces pertinentes de ce système, et des tas se sont produits. plusieurs fois au cours du processus. Débordement de mémoire, animation suspendue du système, l'outil d'analyse de la mémoire Java intégré à Java a analysé le fichier de vidage généré par le système et a constaté qu'un objet n'avait pas été recyclé, occupant 98 % de la mémoire tas. pour analyser le thread où se trouve l'objet, et a constaté qu'il est lié à l'utilisation des threads resttemplate, et que les objets de tas générés par les threads associés ne sont pas effacés après la fermeture de resttemplate. La recherche d'informations pertinentes en ligne montre que le HttpClient traditionnel est enclin à. débordement de mémoire de tas dans des conditions de volume de requêtes et de concurrence élevées, lors de l'utilisation d'Apache. Ce phénomène se produit rarement dans l'instance HttpClient CloseableHttpClient, et RestTemplate utilise org.springframework.http.client.ClientHttpRequest par défaut, qui doit être remplacé dans le fichier de configuration ;
Cet article enregistre principalement la configuration de RestTemplate dans springboot .
1. Ajouter des dépendances :
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.3</version> </dependency>
2. Configurer les attributs liés à CloseableHttpClient et configurer des connexions de nettoyage régulières
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. Remplacez le httpClient par défaut dans TestTemplate
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() { ThreadPooolTaskScheduler scheduler = new ThreadPooolTaskScheduler(); scheduler.setThreadNamePrefix("poolScheduler"); scheduler.setPoolSize (50); return scheduler; } }
4. Injectez la classe RestTemplate dans :
@Bean public RestTemplate restTemplate(RestTemplateBuilder builder){ return builder.build(); }
À ce stade, RestTemplate peut être utilisé normalement.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!