SpringBoot で RestTemplate を構成する方法

不言
リリース: 2018-09-20 14:44:09
オリジナル
4599 人が閲覧しました

この記事の内容は 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&#39;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 サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!