遇到的问题
客户端程序退出时报如下错误
2023-02-26 09:18:08.342 [main-EventThread] ERROR o.apache.curator.framework.recipes.cache.NodeCache -
java.lang.IllegalStateException: Expected state [STARTED] was [STOPPED]
at org.apache.curator.shaded.com.google.common.base.Preconditions.checkState(Preconditions.java:823)
at org.apache.curator.framework.imps.CuratorFrameworkImpl.checkState(CuratorFrameworkImpl.java:423)
at org.apache.curator.framework.imps.CuratorFrameworkImpl.checkExists(CuratorFrameworkImpl.java:450)
at org.apache.curator.framework.recipes.cache.NodeCache.reset(NodeCache.java:261)
at org.apache.curator.framework.recipes.cache.NodeCache.access$100(NodeCache.java:60)
at org.apache.curator.framework.recipes.cache.NodeCache$2.process(NodeCache.java:104)
at org.apache.curator.framework.imps.NamespaceWatcher.process(NamespaceWatcher.java:77)
at org.apache.zookeeper.ClientCnxn$EventThread.processEvent(ClientCnxn.java:580)
at org.apache.zookeeper.ClientCnxn$EventThread.run(ClientCnxn.java:555)
业务简单描述
环境
名称 | 版本 |
---|---|
JDK | 17 |
SpringBoot | 2.7.9 |
Dubbo | 3.1.7 |
Client端相关代码
@Slf4j
@EnableDubbo
@SpringBootApplication
public class Application implements CommandLineRunner {
@Value("${spring.profiles.active}")
private String springProfile;
@DubboReference(
version = "${services.version}"
, url = "${services.url}")
private TestServices services;
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);
ApplicationModel.defaultModel().destroy();
//System.exit(SpringApplication.exit(ctx, () -> 0));
}
@Override
public void run(String... strings) {
log.info(">>>>>>{}<<<<<<", springProfile);
log.info("Result:{}", services.test());
}
}
Client端pom中依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.9</version>
<relativePath/>
</parent>
<properties>
<dubbo.version>3.1.7</dubbo.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
......
<dependencies>
<!-- .............................................. spring boot ...-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- .............................................. dubbo ...-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
<exclusions>
<exclusion>
<artifactId>slf4j-reload4j</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
yml配置
server:
shutdown: graceful
dubbo:
application:
name: test-consumer
registry:
id: test-consumer
address: zookeeper://192.168.1.100:2181
config-center:
address: zookeeper://192.168.1.100:2181
metadata-report:
address: zookeeper://192.168.1.100:2181
consumer:
timeout: 3000
check: false
retries: 0
services:
version: 1.0.0
url:
望赐教!
该回答引用GPTᴼᴾᴱᴺᴬᴵ
根据您提供的信息,看起来问题出现在您的 CuratorFramework 调用。具体来说,错误信息中的 java.lang.IllegalStateException 表示您的代码正在尝试使用已停止的 CuratorFramework 对象进行操作,而这显然是不允许的。
可能的原因之一是在客户端程序退出时没有正确关闭 CuratorFramework 对象,导致该对象在程序退出时仍处于已启动状态,但此时已无法继续使用该对象进行操作。
为解决这个问题,您可以尝试在客户端程序退出时显式地关闭 CuratorFramework 对象,例如:
CuratorFramework client = ...; // 获取 CuratorFramework 对象
client.close(); // 关闭对象
另外,您的代码中似乎缺少了变量 key 的定义,这可能会导致编译错误或运行时异常。请确保 key 变量已经被正确定义和初始化。
该回答引用ChatGPT
根据报错信息可以看出,NodeCache对象的状态不符合期望,期望状态是 STARTED,但实际状态是 STOPPED,所以触发了 IllegalStateException 异常。
可能原因是,当你的程序退出时,NodeCache 对象并没有被正确关闭,导致其状态仍然是 STOPPED,而不是 CLOSED。这可能会导致 Zookeeper 客户端出现问题。
你可以尝试在程序退出前手动关闭 NodeCache 对象,如下所示:
// 在程序退出前手动关闭 NodeCache 对象
@DubboReference(version = "${services.version}", url = "${services.url}")
private TestServices services;
private NodeCache nodeCache;
@Override
public void run(String... strings) {
// 创建 NodeCache 对象并启动
nodeCache = new NodeCache(client, path, false);
nodeCache.start();
log.info(">>>>>>{}<<<<<<", springProfile);
log.info("Result:{}", key, services.test());
}
@PreDestroy
public void onDestroy() throws Exception {
// 程序退出时手动关闭 NodeCache 对象
if (nodeCache != null) {
nodeCache.close();
}
}
你也可以尝试将 NodeCache 对象注入到 Spring 容器中,然后使用 @PreDestroy 注解在程序退出前手动关闭 NodeCache 对象。
参考GPT和自己的思路,根据报错信息,问题可能出在 NodeCache 上,该类是 Curator Framework 提供的缓存节点数据的类,它能够监听指定节点的变化并缓存节点的数据,当节点发生变化时会触发监听事件。在该异常中,异常信息显示 NodeCache 的状态是 STOPPED,而程序期望的状态应该是 STARTED,这可能是因为程序在退出时没有正确地关闭 NodeCache 导致的。
解决方法如下:
1.在程序退出时,显示地调用 NodeCache 的 close 方法来关闭缓存,释放资源,例如:
@PreDestroy
public void destroy() throws IOException {
nodeCache.close();
}
2.如果不希望在程序退出时关闭 NodeCache,可以将 NodeCache 对象设置为 Daemon 线程,这样程序退出时不会阻止 JVM 关闭,例如:
nodeCache.setExecutor(Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}));
这样就可以在程序退出时不阻止 JVM 关闭,从而避免了可能因为 NodeCache 未正确关闭而引起的错误。
你这个错误表明 NodeCache 实例在 Zookeeper 的连接已经关闭的情况下被使用,因此出现了异常状态,你需要确保在退出程序之前没有关闭 CuratorFramework 实例,可以通过将 dubbo.shutdown.wait 属性设置为 5000 或更长时间来解决这个问题
springboot集成dubbo踩坑文档
借鉴下,非常详细
https://blog.csdn.net/bug01111/article/details/124178275
为啥客户端要退出?我没理解
不知道你这个问题是否已经解决, 如果还没有解决的话:Zookeeper客户端断开链接时,可能会出现ConnectionLossException异常,该异常表明客户端连接断开,无法更新或访问数据。一般来说,该异常是由网络连接问题或服务器故障导致的。可以尝试检查网络连接,或重启Zookeeper服务器,以解决该问题。