线上问题解决系列——记一次HTTP连接池导致的Java服务雪崩
Posted 架构师卡尔
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线上问题解决系列——记一次HTTP连接池导致的Java服务雪崩相关的知识,希望对你有一定的参考价值。
[INFO][2021-04-11T09:09:14.917+0800][http-nio-8099-exec-148]
[ERROR][2021-04-11T09:37:01.618+0800][http-nio-8099-exec-148]
org.apache.http.impl.execchain.RequestAbortedException: Request execution failed
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:199)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
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:108)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
at com.xxx.xxx.xxx.xxx.XxxxxxClient.execute(XxxxxxxClient.java:49)
// 这里就是抛出异常的地方,使用http连接池
HttpResponse httpResponse = httpClient.execute(httpPost);
if (httpResponse == null) {
throw new RuntimeException("HttpResponse is null");
}
if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
// 非200状态,直接抛出异常
throw new RuntimeException(httpResponse.toString());
}
// 读取返回结果,后续处理逻辑
response = EntityUtils.toString(httpResponse.getEntity());
http请求调用时间过长
获取不到可用连接
EntityUtils.toString(httpResponse.getEntity());
public static String toString(final HttpEntity entity) throws IOException, ParseException {
Args.notNull(entity, "Entity");
return toString(entity, ContentType.get(entity));
}
private static String toString(
final HttpEntity entity,
final ContentType contentType) throws IOException {
final InputStream inStream = entity.getContent();
if (inStream == null) {
return null;
}
try {
Args.check(entity.getContentLength() <= Integer.MAX_VALUE,
"HTTP entity too large to be buffered in memory");
int capacity = (int)entity.getContentLength();
if (capacity < 0) {
capacity = DEFAULT_BUFFER_SIZE;
}
Charset charset = null;
if (contentType != null) {
charset = contentType.getCharset();
if (charset == null) {
final ContentType defaultContentType = ContentType.getByMimeType(contentType.getMimeType());
charset = defaultContentType != null ? defaultContentType.getCharset() : null;
}
}
if (charset == null) {
charset = HTTP.DEF_CONTENT_CHARSET;
}
final Reader reader = new InputStreamReader(inStream, charset);
final CharArrayBuffer buffer = new CharArrayBuffer(capacity);
final char[] tmp = new char[1024];
int l;
while((l = reader.read(tmp)) != -1) {
buffer.append(tmp, 0, l);
}
return buffer.toString();
} finally {
// 这里,关闭了输入流,因此可以释放连接
inStream.close();
}
}
名称: http-nio-8099-exec-6
状态: java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@15c3ce0e上的WAITING
总阻止数: 0, 总等待数: 17
堆栈跟踪:
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
org.apache.http.pool.AbstractConnPool.getPoolEntryBlocking(AbstractConnPool.java:393)
org.apache.http.pool.AbstractConnPool.access$300(AbstractConnPool.java:70)
org.apache.http.pool.AbstractConnPool$2.get(AbstractConnPool.java:253)
- 已锁定 org.apache.http.pool.AbstractConnPool$2@123689b2
org.apache.http.pool.AbstractConnPool$2.get(AbstractConnPool.java:198)
org.apache.http.impl.conn.PoolingHttpClientConnectionManager.leaseConnection(PoolingHttpClientConnectionManager.java:306)
org.apache.http.impl.conn.PoolingHttpClientConnectionManager$1.get(PoolingHttpClientConnectionManager.java:282)
org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:190)
org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
com.xxx.xxx.xxx.xxx.XxxxxxClient.execute(XxxxxxClient.java:49)
以上是关于线上问题解决系列——记一次HTTP连接池导致的Java服务雪崩的主要内容,如果未能解决你的问题,请参考以下文章
记一次 HttpClient 连接池参数引发的雪崩问题的定位分析解决过程!
记一次线上Java程序导致服务器CPU占用率过高的问题排除过程