Der Inhalt dieses Artikels befasst sich mit der Methode zur Konfiguration von RestTemplate in Springboot. Ich hoffe, dass er für Freunde hilfreich ist.
Hintergrund: Ich habe kürzlich bei der Arbeit ein Zwischensystem erstellt und dabei das RestTemplate-Framework verwendet, um die Restful-Schnittstelle des dritten Systems aufzurufen. Der Aufrufer verwendete Polling, um die relevanten Schnittstellen dieses Systems aufzurufen, und es kam zu Heaps Viele Male während des Prozesses hat das integrierte Java-Speicheranalysetool die vom System generierte Speicherauszugsdatei analysiert und festgestellt, dass ein Objekt nicht recycelt wurde und 98 % des Heap-Speichers belegt Um den Thread zu analysieren, in dem sich das Objekt befindet, wurde festgestellt, dass es mit der Verwendung von Resttemplate-Threads zusammenhängt und die von verwandten Threads generierten Heap-Objekte nach dem Schließen von Resttemplate nicht gelöscht werden. Die Online-Suche nach relevanten Informationen zeigt, dass herkömmlicher HttpClient dazu anfällig ist Heap-Speicherüberlauf bei hohem Anforderungsvolumen und hohen Parallelitätsbedingungen bei Verwendung von Apache. Dieses Phänomen tritt selten in der HttpClient-Instanz CloseableHttpClient auf, und RestTemplate verwendet standardmäßig org.springframework.http.client.ClientHttpRequest, das in der Konfigurationsdatei ersetzt werden muss;
In diesem Artikel wird hauptsächlich die Konfiguration von RestTemplate in Springboot beschrieben.
1. Abhängigkeiten hinzufügen:
<!-- 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-bezogene Attribute konfigurieren und regelmäßige Bereinigungsverbindungen einrichten
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. Ersetzen Sie den Standard-httpClient in 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. Fügen Sie die RestTemplate-Klasse in die Startup-Klasse ein:
@Bean public RestTemplate restTemplate(RestTemplateBuilder builder){ return builder.build(); }
An diesem Punkt kann RestTemplate normal verwendet werden.
Das obige ist der detaillierte Inhalt vonSo konfigurieren Sie RestTemplate in Springboot. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!