Java向ES库中插入数据报错:I/O reactor status: STOPPED

这篇具有很好参考价值的文章主要介绍了Java向ES库中插入数据报错:I/O reactor status: STOPPED。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


一、问题

在使用Java向ES库中插入数据时,第一次成功插入,第二次出现以下错误:
java.lang.IllegalStateException: Request cannot be executed; I/O reactor status: STOPPED at

问题原因

这里显示是连接中断,第一次遇到这个问题,比较疑惑为什么es的客户端会中断,理论上es client 是长连接,不停的有数据写入,连接一致存在,除非有服务端异常。在elasticsearch服务端查看日志,没有任何异常信息。

网上搜索错误信息原来是 Apache HTTPComponents 异步客户端问题。es官网有个issues详细的记录的这个问题的原因和修复建议。

官方的意见是 Apache HTTPComponents 异步客户端 使用了一个内部的I/O reactor 分发IO event。在某些情况下,IO reactor会记录程序调用栈中的异常或者Java NOI库中的异常,如果这些异常不被处理,I/O reactor会直接关闭,es client不可用,此时只能重启服务。es client中试图增加一个默认的 I/O reactor 异常处理逻辑但是在做了一些尝试后发现捕获I/O reactor后会导致SSL中断。而HTTPComponents 在版本5中已经修复了这个问题,最终官网给的建议是等待版本升级。

二、解决思路

解决问题的过程中参考了以下文档:
https://www.cnblogs.com/yangchongxing/p/15440197.html
https://github.com/elastic/elasticsearch/issues/42133
https://zhuanlan.zhihu.com/p/384269417
https://cloud.tencent.com/developer/article/1806886

主要获得解决方法的是以下:
https://github.com/elastic/elasticsearch/issues/39946
主要引用以下:
java.lang.illegalstateexception: request cannot be executed; i/o reactor sta,Elasticsearch 的使用,java,elasticsearch,开发语言
大概意思是说:
在每个线程需要时创建一个新的客户端,并在方法结束时关闭。这就解决了问题。
结合GPT获取解决方案:

import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;

public class EsClientManager {
    private final ExecutorService executorService = Executors.newFixedThreadPool(10);
    private final ThreadLocal<RestHighLevelClient> CLIENT_THREAD_LOCAL = ThreadLocal.withInitial(() -> {
        RestHighLevelClient client = null;
        try {
            client = RestHighLevelClient.builder(new HttpHost("localhost", 9200, "http")).build();
            return client;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    });

    public RestHighLevelClient getClient() {
        return CLIENT_THREAD_LOCAL.get();
    }

    public void closeClient(RestHighLevelClient client) {
        CLIENT_THREAD_LOCAL.remove();
        if (client != null) {
            executorService.execute(() -> {
                try {
                    client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }
    }
}

在使用时,同样可以这样:

public class MyService {
    public void someMethod() {
        RestHighLevelClient client = EsClientManager.getClient();
        try {
            // 执行操作
        } finally {
            EsClientManager.closeClient(client);
        }
    }
}

这样,每个线程都会从EsClientManager获取一个客户端,并在方法结束时自动关闭。

线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,进一步,优化:
文章来源地址https://www.toymoban.com/news/detail-843503.html

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.LinkedBlockingQueue;

public class EsClientManager {
    private final ExecutorService executorService;
    private final ThreadLocal<RestHighLevelClient> CLIENT_THREAD_LOCAL = ThreadLocal.withInitial(() -> {
        RestHighLevelClient client = null;
        try {
            client = RestHighLevelClient.builder(new HttpHost("localhost", 9200, "http")).build();
            return client;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    });

    public EsClientManager() {
        // 配置 ThreadPoolExecutor
        int corePoolSize = 10; // 核心线程数
        int maximumPoolSize = 10; // 最大线程数
        long keepAliveTime = 0L; // 空闲线程等待新任务的最长时间
        TimeUnit unit = TimeUnit.MILLISECONDS; // keepAliveTime的时间单位
        int queueCapacity = 100; // 工作队列的容量
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            corePoolSize,
            maximumPoolSize,
            keepAliveTime,
            unit,
            new LinkedBlockingQueue<>(queueCapacity), // 工作队列
            runnable -> {
                Thread thread = new Thread(runnable);
                thread.setDaemon(false); // 设置线程是否为守护线程,false表示非守护线程
                return thread;
            }
        );
        this.executorService = Executors.unconfigurableExecutorService(executor);
    }

    public RestHighLevelClient getClient() {
        return CLIENT_THREAD_LOCAL.get();
    }

    public void closeClient(RestHighLevelClient client) {
        CLIENT_THREAD_LOCAL.remove();
        if (client != null) {
            executorService.execute(() -> {
                try {
                    client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }
    }

    // 添加方法以允许关闭executorService
    public void shutdown() {
        executorService.shutdown();
    }

    public boolean isShutdown() {
        return executorService.isShutdown();
    }

    public boolean isTerminated() {
        return executorService.isTerminated();
    }
}

到了这里,关于Java向ES库中插入数据报错:I/O reactor status: STOPPED的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java 调用Elasticsearch报错java.lang.IllegalStateException: Request cannot be executed; I/O reactor statu

    一、问题描述 线上ES查询服务出现奇怪的问题,调用es查询数据的接口进行过一次查询,过几分钟之后再次用这个接口进行查询就不行了。 二、报错排查 简短报错:java.lang.IllegalStateException: Request cannot be executed; I/O reactor status: STOPPED 三、解决问题 经过排查发现可能是出现异常

    2024年02月20日
    浏览(46)
  • java查询ES数据时,报错missing authentication credentials for REST request

     通过java代码查询ES里数据时,报错缺少身份认证凭证,但在注册RestClient的时候已经提供了用户名、密码,并且测试环境没有出现这个问题,生产环境报错。 如下,在查询数据时new了ElasticsearchClient,使用该客户端进行查询,注册client时提供了用户密码 注册client的代码  网上

    2024年04月17日
    浏览(42)
  • ES 数据插入异常原因分析

    24-01-23.15:50:18.635 [I/O dispatcher 1] WARN  org.elasticsearch.client.RestClient  - request [HEAD http://localhost:9200/alarm_msg?ignore_throttled=falseinclude_type_name=trueignore_unavailable=falseexpand_wildcards=openallow_no_indices=true] returned 1 warnings: [299 Elasticsearch-7.17.13-2b211dbb8bfdecaf7f5b44d356bdfe54b1050c13 \\\"[ignore_throttled] param

    2024年01月24日
    浏览(74)
  • sift-1M数据集的读取及ES插入数据

    sift是检查ann近邻召回率的标准数据集,ann可以选择faiss,milvus等库或者方法;sift数据分为query和base,以及label(groundtruth)数据。本文采用sift-1M进行解读,且看如下: 官方链接地址:Evaluation of Approximate nearest neighbors: large datasets   这是啥问题?我怀疑是下载失败,删除重新下

    2024年02月13日
    浏览(34)
  • java selenium问题解决,版本号对应,仍报错java.io.IOException: Invalid Status code=403 text=Forbidden

    报错截图 java.io.IOException: Invalid Status code=403 text=Forbidden Exception in thread \\\"main\\\" org.openqa.selenium.remote.http.ConnectionFailedException: Unable to establish websocket connection to http://localhost:60613/devtools/browser/747cc62c-8bb8-4828-ab4e-afa69400a604 Build info: version: \\\'4.1.2\\\', revision: \\\'9a5a329c5a\\\' System info: host: \\\'LAPTOP-

    2024年02月11日
    浏览(57)
  • Postman报错 status: 500,error: Internal Server Error,数据无法通过json传入后端。

    原因:没有加@RequestBody注解 错误如下: {     \\\"timestamp\\\": \\\"2022-10-08T12:28:11.503+00:00\\\",     \\\"status\\\": 500,     \\\"error\\\": \\\"Internal Server Error\\\",     \\\"path\\\": \\\"/books\\\" } 测试数据: 控制台:   解决方法: 把要传入的book前面加入@RequestBody 而@RequestBody主要用来接收前端传递给后端的json字符

    2024年02月11日
    浏览(57)
  • Es批量插入数据报异常Unable to parse response body

    Unable to parse response body org.elasticsearch.client.ResponseException: method [POST], host [http://xx.xxx.xxx.xx:9201], URI [/_bulk?timeout=1m], status line [HTTP/1.1 413 Request Entity Too Large] 因为 批量提交 提交内容请求实体太大超过了es中设置的最大值,Bulk 默认设置批量提交的数据量不能超过   100M 官网说明:

    2024年02月12日
    浏览(49)
  • SqlServer插入数据不报错但查询不到数据

    近日,某使用SqlServer作为数据库的系统,由于服务器磁盘损坏修复后,部分数据一直无法入库,进一步跟踪收集现象,发现以下特点: 这些数据抽取出来使用SQL直接入库,没有提示数据影响行数,数据库无法查询到这部分数据; JDBC入库返回影响行数为-2; 仅有部分数据无法

    2024年02月12日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包