#multithreading #spring-boot #resttemplate
#многопоточность #пружинная загрузка #resttemplate
Вопрос:
Я использую 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.access$200(AbstractConnPool.java:69)
at org.apache.http.pool.AbstractConnPool$2.get(AbstractConnPool.java:246)
- locked <0x00000000e728c1e8> (a org.apache.http.pool.AbstractConnPool$2)
at org.apache.http.pool.AbstractConnPool$2.get(AbstractConnPool.java:193)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.leaseConnection(PoolingHttpClientConnectionManager.java:303)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager$1.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>
Из RestTemplate будет поступать более 500 запросов в минуту.
Любая помощь в том, что пошло не так с этим API. будет ли RestTemplate не закрывать сокет в любом сценарии?
Спасибо, Хари
Ответ №1:
Я думаю, что причина, по которой 90% потоков находятся в состоянии блокировки, заключается в том, что потоки заблокированы / ожидают ответа API. RestTemplate является блокирующим или синхронным в соответствии с документацией:
Вы можете переключиться на асинхронный или неблокирующий веб-клиент, и вы должны получить гораздо лучшую пропускную способность на поток:
Другим вариантом было бы создавать поток для каждого соединения, если это возможно, но я думаю, что асинхронный клиент будет масштабироваться лучше, если у вас будет возможность переносить ваш код.
Приветствия,
Кайл
Комментарии:
1. Но я установил тайм-аут чтения и тайм-аут подключения на 3 секунды….
2. это не ответ на вопрос. Как асинхронная неблокировка помогает решить проблему? Если он ожидает блокировки, асинхронная неблокировка ухудшит ситуацию, то есть будет накоплено огромное количество взаимоблокировочных потоков. Разве это не так или я что-то здесь упускаю?