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 是阻塞的还是同步的:
您可以切换到异步或 non-blocking WebClient,您应该会获得更好的每个线程吞吐量:
另一种选择是在可能的情况下为每个连接生成一个线程,但我认为如果您能够移植代码,异步客户端的扩展性会更好。
干杯,
凯尔
我正在使用 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 是阻塞的还是同步的:
您可以切换到异步或 non-blocking WebClient,您应该会获得更好的每个线程吞吐量:
另一种选择是在可能的情况下为每个连接生成一个线程,但我认为如果您能够移植代码,异步客户端的扩展性会更好。
干杯,
凯尔