笔者,从事大型项目监控设计流程,有一次需要将ES整合到项目中,ELK的那一套日志作为用户接口的调用基础,类似于采集、清洗、转换、存储。

刚开始设计代码及流程,之后把代码进行优化抽取,封装client等。

发现当我们本地启动项目第一次测试完全顺利,不关闭服务的情况下第二次再次测试发现报错java.lang.RuntimeException: Request cannot be executed; I/O reactor status: STOPPED

java.lang.RuntimeException: Request cannot be executed; I/O reactor status: STOPPED
        at org.elasticsearch.client.RestClient.extractAndWrapCause(RestClient.java:796)
        at org.elasticsearch.client.RestClient.performRequest(RestClient.java:218)
        at org.elasticsearch.client.RestClient.performRequest(RestClient.java:205)
        at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:1454)
        at org.elasticsearch.client.RestHighLevelClient.performRequest(RestHighLevelClient.java:1424)
        at org.elasticsearch.client.RestHighLevelClient.performRequestAndParseEntity(RestHighLevelClient.java:1394)
        at org.elasticsearch.client.RestHighLevelClient.search(RestHighLevelClient.java:930)
        at com.sitech.cmap.schedule.app.ElkSyncAppImpl.collectElkData(ElkSyncAppImpl.java:1326)
        at com.sitech.cmap.schedule.app.ElkSyncAppImpl.lambda$perSync$0(ElkSyncAppImpl.java:104)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: Request cannot be executed; I/O reactor status: STOPPED
        at org.apache.http.util.Asserts.check(Asserts.java:46)
        at org.apache.http.impl.nio.client.CloseableHttpAsyncClientBase.ensureRunning(CloseableHttpAsyncClientBase.java:90)
        at org.apache.http.impl.nio.client.InternalHttpAsyncClient.execute(InternalHttpAsyncClient.java:123)
        at org.elasticsearch.client.RestClient.performRequest(RestClient.java:214)
        ... 10 more

见诸多网友分析各种各样,情形不一。比如,多线程导致错误、OOM导致错误、官方自带bug等

于是乎,我认真的看了一下代码,既然是封装代码做成config的bean,每次开机自启生成一个client对象,这个对象再业务代码中并不会去重新调用,服务开启就生成了,原则上只要不断开链接就一直用的。 

问题就在这个地方,因为我们业务代码是原始的:连接客户端--->查询---->断开,那么再断开close的时候就把服务初始化生成的惟一的client给关了,于是可以看到client的属性状态由原来正常的activity变成stooped,连接被关闭了当然调用报错了。

侧面反映源码的重要性。

OS: 对症下药,方能药到病除。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐