이 글의 내용은 springboot에서 RestTemplate을 구성하는 방법에 대한 내용입니다. 필요한 친구들이 참고하면 좋을 것 같습니다.
Background: 최근 직장에서 RestTemplate 프레임워크를 사용하여 세 번째 시스템의 Restful 인터페이스를 호출하는 중간 시스템을 구축했습니다. 호출자는 폴링을 사용하여 이 시스템의 관련 인터페이스를 호출합니다. 이 기간 동안 많은 사람들이 처음으로 힙 메모리 오버플로가 발생하고 시스템 애니메이션이 정지되었습니다. General Java와 함께 제공되는 Java 메모리 분석 도구는 시스템에서 생성된 덤프 파일을 분석하여 그렇지 않은 개체가 있음을 발견했습니다. MAT를 사용하여 객체가 위치한 스레드를 분석한 결과 Resttemplate의 관련 스레드와 관련 스레드에 의해 생성된 힙 객체가 Resttemplate이 삭제된 후에도 지워지지 않습니다. 관련 정보를 온라인으로 검색해 보면 기존 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 TestTemplate에서 기본 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() { ThreadPooolTaskScheduler scheduler = new ThreadPooolTaskScheduler(); scheduler.setThreadNamePrefix("poolScheduler"); scheduler.setPoolSize (50); return scheduler; } }
@Bean public RestTemplate restTemplate(RestTemplateBuilder builder){ return builder.build(); }
위 내용은 springboot에서 RestTemplate을 구성하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!