この記事の内容は springboot での RestTemplate の設定方法に関するものです。必要な方は参考にしていただければ幸いです。
背景: 最近、中間システムが作業中に構築され、RestTemplate フレームワークを使用して 3 番目のシステムの RESTful インターフェイスを呼び出しました。呼び出し元はポーリングを使用して、このシステムの関連インターフェイスを呼び出しました。メモリ オーバーフロー、システムの一時停止アニメーション、一般的な Java の組み込み Java メモリ分析ツールがシステムによって生成されたダンプ ファイルを分析したところ、オブジェクトがリサイクルされておらず、ヒープ メモリの 98% を占有していることが判明しました。オブジェクトが配置されているスレッドを分析したところ、resttemplate スレッドの使用に関連していることがわかり、resttemplate が閉じられた後も関連スレッドによって生成されたヒープ オブジェクトがクリアされないことがわかりました。オンラインで関連情報を検索すると、従来の HttpClient がヒープを発生させる傾向があることがわかりました。 Apache を使用しているときに、リクエスト量が多く同時実行性が高い状況でのメモリ オーバーフロー
##この記事では主に 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
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 のデフォルトの httpClient をスタートアップ クラスに挿入します。 ##
@Bean public RestTemplate restTemplate(RestTemplateBuilder builder){ return builder.build(); }# この時点では、RestTemplate は正常に使用できます。
以上がSpringBoot で RestTemplate を構成する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。