RestTemplate.exchange:锁定线程

RestTemplate.exchange: Locking threads

我正在使用 RestTemplate 与 API 交谈。最近遇到这个问题,几乎90%的线程都处于等待状态。

p685934-2328" #2328 prio=5 os_prio=0 tid=0x00000000023b6000 nid=0x2f1f waiting on condition [0x00007f6df703f000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000000ab0eaae8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
    at org.apache.http.pool.AbstractConnPool.getPoolEntryBlocking(AbstractConnPool.java:380)
    at org.apache.http.pool.AbstractConnPool.access0(AbstractConnPool.java:69)
    at org.apache.http.pool.AbstractConnPool.get(AbstractConnPool.java:246)
    - locked <0x00000000e728c1e8> (a org.apache.http.pool.AbstractConnPool)
    at org.apache.http.pool.AbstractConnPool.get(AbstractConnPool.java:193)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.leaseConnection(PoolingHttpClientConnectionManager.java:303)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.get(PoolingHttpClientConnectionManager.java:279)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:191)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
    at org.springframework.http.client.HttpComponentsClientHttpRequest.executeInternal(HttpComponentsClientHttpRequest.java:87)
    at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
    at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:723)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:680)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:600)

RestTemplate 定义如下。

HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
clientHttpRequestFactory.setConnectTimeout( 3000 );
clientHttpRequestFactory.setReadTimeout( 3000 );

SSLContext sslContext = SSLContexts.custom()
                .loadTrustMaterial((X509Certificate[] chain, String authType) -> true)
                .build();

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
              sslContext, (String hostname, SSLSession session) -> true);
clientHttpRequestFactory.setHttpClient(HttpClients.custom()
              .setSSLSocketFactory(sslsf).build());



RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory);

附加信息

Spring boot version : 2.0.3.RELEASE

<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpclient</artifactId>
  <version>4.5.5</version>
</dependency>

每分钟超过 500 个请求将来自 RestTemplate。

有关此问题的任何帮助 API。 RestTemplate 在任何情况下都不会关闭套接字吗?

谢谢, 哈里

我认为 90% 的线程处于锁定状态的原因是线程被阻塞/等待 API 响应。根据文档,RestTemplate 是阻塞的还是同步的:

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html

您可以切换到异步或 non-blocking WebClient,您应该会获得更好的每个线程吞吐量:

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/reactive/function/client/WebClient.html

另一种选择是在可能的情况下为每个连接生成一个线程,但我认为如果您能够移植代码,异步客户端的扩展性会更好。

干杯,

凯尔