【踩坑专栏】java.lang.IllegalStateException: Expected state [STARTED] was [STOPPED]

本文讲述了在A项目通过Dubbo调用B项目接口时遇到的错误,涉及zookeeper连接关闭、依赖包丢失,以及解决过程,重点在于排查和故障恢复。

先介绍下背景,此时使用的是zookeeper+dubbo的注册中心框架,A项目依赖于B项目,我在A项目发起对B项目接口的调用的时候报了这么一个错,

java.lang.IllegalStateException: Expected state [STARTED] was [STOPPED]

初看我还以为是zookeeper关闭连接导致的,看了下zookeeper server,确实有日志如下:

2021-12-29 10:21:58,680 [myid:] - WARN  [NIOWorkerThread-4:NIOServerCnxn@370] - Exception causing close of session 0x1000002614d0011: 远程主机强迫关闭了一个现有的连接。

难道真的是zookeeper莫名其妙的关闭了?可是看B项目控制台并没有日志说zookeeper关闭连接,查看zookeeper端口也可以查到:

netstat -ano | findstr 2181

在这里插入图片描述

于是觉得可能不是zookeeper的问题,上网查了下,有说是部署的问题的,于是我把A项目clean install了一下,结果报错说B项目的包不存在。看来是B项目的包莫名其妙的没了,把B项目clean install一下,果然A项目可以正常启动了。

第二次再次遇到这个问题时,不是jar依赖的问题,那么从之前的报错上看,就是zookeeper的问题,关掉zookeeper server,重新打开一次zkServer.cmd就好了。

Quartz 框架中出现 `IllegalStateException: Expected state STARTED was STOPPED` 的异常通常与任务调度器的状态管理有关。具体来说,当尝试在调度器已经停止的状态下执行某些操作时,就会抛出此异常。在用户描述的场景中,异常发生在关闭钩子(Shutdown Hook)中上传数据到 Elasticsearch 的过程中,这表明操作尝试在调度器停止后执行了某些依赖于调度器运行状态的逻辑。 ### 原因分析 1. **调度器生命周期管理问题** Quartz 调度器在关闭时会进入 `STOPPED` 状态。如果关闭钩子中执行的 `UploadEsData` 任务尝试使用已经关闭的调度器资源,就会导致 `IllegalStateException`。这通常发生在任务尝试触发新任务或访问调度器 API 时[^1]。 2. **关闭钩子执行时机不当** 如果关闭钩子注册的时机在调度器关闭流程的后期,或者钩子本身执行时间较长,可能会导致调度器资源已被释放,但仍尝试访问这些资源。 3. **线程安全问题** 如果多个线程并发访问调度器资源,尤其是在调度器正在关闭的过程中,可能会出现状态不一致的问题。 ### 解决方案 1. **确保关闭钩子中的操作不依赖调度器状态** 在关闭钩子中执行的操作应尽量避免使用 Quartz 调度器 API 或依赖调度器的运行状态。可以考虑将上传 Elasticsearch 数据的操作封装为独立的服务,不依赖调度器的生命周期。 2. **在调度器关闭前主动取消注册任务或延迟关闭** 可以通过在关闭钩子中使用 `Thread.sleep()` 或异步执行机制,确保上传操作在调度器关闭前完成。例如: ```java Runtime.getRuntime().addShutdownHook(new Thread(() -> { try { // 上传数据到 Elasticsearch uploadDataToElasticsearch(); // 确保上传完成后再继续关闭流程 Thread.sleep(1000); // 可选,等待上传完成 } catch (InterruptedException e) { Thread.currentThread().interrupt(); } })); ``` 3. **检查任务调度状态** 在执行上传任务前,显式检查调度器的状态是否为 `STARTED`。如果调度器已经停止,应跳过相关操作或记录警告信息,而不是直接抛出异常。 4. **使用异步上传机制** 将上传数据到 Elasticsearch 的操作设计为异步任务,并使用独立的线程池或事件队列管理,避免阻塞主线程或依赖调度器状态。 ### 示例代码:异步上传数据 ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class EsDataUploader { private static final ExecutorService executor = Executors.newSingleThreadExecutor(); public static void uploadDataToElasticsearch() { executor.submit(() -> { // 执行上传数据到 Elasticsearch 的逻辑 System.out.println("Uploading data to Elasticsearch..."); // 模拟上传操作 try { Thread.sleep(500); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); } public static void shutdown() { executor.shutdown(); } } ``` 在关闭钩子中调用 `EsDataUploader.shutdown()` 确保资源正确释放。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值