问题
使用ES过程中遇到一个Request cannot be executed; I/O reactor status: STOPPED 的异常,大概意思是和server端的连接异常终止了。出现时机是偶尔出现,同时多节点的应用服务不是都出现。
主要报错信息是:
Request cannot be executed; I/O reactor status: STOPPED
- 后端程序处于假死状态,访问其他接口一直转圈,无法响应内容
- 重启程序之后一切正常
- 详细报错日志为:
- 本地IDEA中一次也没有报这个问题
- 使用JMETER设置50个线程并发访问一个查询大量数据的接口可以稳定复现此问题
原因
程序接口中将一块很大的数据存进JAVA集合中引发了oom,oom异常导致程序宕机,处于假死状态,进而导致 ES-CLIENT 和 ES-SERVER 端的 http 连接异常终止,然后org.apache.http.impl.nio.client.CloseableHttpAsyncClientBase.ensureRunning 方法报异常。
源码:
protected void ensureRunning() {
final Status currentStatus = this.status.get();
Asserts.check(currentStatus == Status.ACTIVE, "Request cannot be executed; " +
"I/O reactor status: %s", currentStatus);
}
public static void check(final boolean expression, final String message, final Object arg) {
if (!expression) {
throw new IllegalStateException(String.format(message, arg));
}
}
- SpringDataElasticsearch 和ES-SERVER 是长链接,只要报了OOM,当前和 ES-SERVER 的连接线程都将报异常,也就是说,虽然OOM只报了一次,但是可能有多个线程都在 Asserts.check 方法中报异常
- 本地idea无法复现的原因是内存配置不同导致的,本地idea内存给的4g。编辑 run/debug configuration ,设置 VM options 和线上环境相同,使用jemter压测本地idea中跑的程序,也能应该复现此问题
解决
- 优化接口,解决OOM问题