Springs RestTemplate默认连接池

Sam*_*Sam 18 spring connection-pooling resttemplate

只是想知道开箱即用的RestTemplate是使用连接池还是每次只是建立一个新的连接?

小智 17

默认情况下,RestTemplate每次都会创建新的Httpconnection,并在完成后关闭连接.

如果您需要在rest模板下有连接池,那么您可以使用池连接的ClientHttpRequestFactory的不同实现.

new RestTemplate(new HttpComponentsClientHttpRequestFactory())
Run Code Online (Sandbox Code Playgroud)

  • 其实,没那么简单。每个 RestTemplate 的连接池都在那里:HttpComponentsClientHttpRequestFactory->HttpClients.createSystem()->HttpClientBuilder->PoolingHttpClientConnectionManager (4认同)

oot*_*ero 7

我相信RestTemplate不会使用连接池来发送请求,它会使用SimpleClientHttpRequestFactory来包装标准JDKHttpURLConnection打开和关闭连接。

确实,您可以配置RestTemplate为使用池化实现,例如,HttpComponentsClientHttpRequestFactory但最有可能的是,您可能还需要配置一些设置以防止请求超时。

我已经在Spring的RestTemplate请求超时故障排除中写了关于此问题的博客。

  • @EugeneMakarenko,为什么你需要 10 个实例?RestTemplate 是线程安全的。您可以使用同一个 RestTemplate 实例向多个服务发送请求。只需正确配置它,这样一项缓慢的服务就不会劫持整个池。 (2认同)

Vol*_*ret 7

是的,Spring RestTemplateBuilder使用apache httpclient进行池化(用法)。RestTemplateBuilder创建HttpComponentsClientHttpRequestFactory并使用HttpClientBuilder。HttpClientBuilder是最有趣的():

                s = System.getProperty("http.maxConnections", "5"); 
                int max = Integer.parseInt(s); 
                poolingmgr.setDefaultMaxPerRoute(max); 
                poolingmgr.setMaxTotal(2 * max); 
Run Code Online (Sandbox Code Playgroud)

因此,默认情况下,每个路由(主机)的池大小等于5。总池大小=10。要检查连接池日志记录集的日志记录级别,如下所示:

org.apache.http.impl.conn.PoolingHttpClientConnectionManager=TRACE
Run Code Online (Sandbox Code Playgroud)

  • RestTemplateBuilder?这个答案可能是正确的,但在 spring 依赖项中没有看到 RestTemplateBuilder。如果您执行 new RestTemplate(),您将获得 SimpleClientHttpRequestFactory 而不是 HttpComponentsClientHttpRequestFactory。使用新的 RestTemplate(HttpComponentsClientHttpRequestFactory); 似乎是要走的路。 (3认同)
  • 这个答案是正确的。如果您在浏览 Internet 时发现不同的默认值(例如 2/ 20 或 5/25),请不要感到困惑。如果您直接实例化`PoolingHttpClientConnectionManager`,则这些适用([来源](https://github.com/apache/httpcomponents-client/blob/6ba9b4acdcba411a035503e3eae9e17b64bcc59b/httpclient5/src/main/java/org/apache/hc/client5/http/ impl/io/PoolingHttpClientConnectionManager.java#L110-L111))。这些年来这些值也发生了变化......但正如所说,Spring Boot 使用“HttpClientBuilder”,它有自己的默认值。 (3认同)

sen*_*982 7

您可以在RestTemplate那里创建一个 Bean并在那里进行配置:

    @Bean
    public RestTemplate restTemplate() {
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(100);
        connectionManager.setDefaultMaxPerRoute(20);

    RequestConfig requestConfig = RequestConfig
        .custom()
        .setConnectionRequestTimeout(5000) // timeout to get connection from pool
        .setSocketTimeout(5000) // standard connection timeout
        .setConnectTimeout(5000) // standard connection timeout
        .build();

    HttpClient httpClient = HttpClientBuilder.create()
                                             .setConnectionManager(connectionManager)
                                             .setDefaultRequestConfig(requestConfig).build();

    ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);


    return new RestTemplate(requestFactory);
}
Run Code Online (Sandbox Code Playgroud)

你可以做很多配置。参考https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/client/HttpClientBuilder.html

编辑

如果您想使用千分尺度量,您还应该使用RestTemplateBuilder来构建 RestTemplate。

  • 我真的很喜欢你的解决方案,我想建议 2 个改进: 1. 使用 RestTemplateBuilder 2. 还设置 setConnectTimeout() 我可以编辑你的答案还是我应该更好地发布一个单独的答案? (4认同)