解决Redis java.lang.IllegalStateException: Cannot connect, Event executor group is terminated

问题产生背景

  • 写了个基于zset的消息队列(因为公司redis还是3.2.9的,没法用stream),然后有个线程一直轮询取数据。
    在这里插入图片描述

  • 然后我关闭应用时可能会报Cannot connect, Event executor group is terminated,如下所示。
    在这里插入图片描述

 Exception in thread "loop-redis-queue" java.lang.IllegalStateException: Cannot connect, Event executor group is terminated.
	at io.lettuce.core.AbstractRedisClient.initializeChannelAsync(AbstractRedisClient.java:283)
	at io.lettuce.core.RedisClient.connectStatefulAsync(RedisClient.java:314)
	at io.lettuce.core.RedisClient.connectStandaloneAsync(RedisClient.java:271)
	at io.lettuce.core.RedisClient.connect(RedisClient.java:204)
	at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.lambda$getConnection$1(StandaloneConnectionProvider.java:113)
	at java.util.Optional.orElseGet(Optional.java:267)
	at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.getConnection(StandaloneConnectionProvider.java:113)
	at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getNativeConnection(LettuceConnectionFactory.java:1110)
	at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getConnection(LettuceConnectionFactory.java:1091)
	at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getSharedConnection(LettuceConnectionFactory.java:872)
	at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getConnection(LettuceConnectionFactory.java:347)
	at org.springframework.data.redis.core.RedisConnectionUtils.doGetConnection(RedisConnectionUtils.java:134)
	at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:97)
	at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:84)
	at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:212)
	at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:185)
	at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:96)
	at org.springframework.data.redis.core.DefaultZSetOperations.rangeByScore(DefaultZSetOperations.java:197)
	at com.springboot.sample.redis.DelayingQueueService.pop(DelayingQueueService.java:88)
	at com.springboot.sample.redis.DelayingQueueService$1.run(DelayingQueueService.java:124)

问题分析

解决方案

  • Spring有对关闭程序,销毁bean回调的扩展,例如实现DisposableBean接口或者 使用@PreDestroy注解。@PreDestroy注解被调用早于DisposableBean接口,我用的@PreDestroy。
  • 增加销毁标记
    /** 是否销毁标记 volatile 保证可见性 **/
    private volatile boolean destroyFlag = false;
  • 修改标记
    @PreDestroy
    public void destroy() throws Exception {
        System.out.println("应用程序已关闭");
        this.destroyFlag = true;
    }
  • 然后在轮询的地方加入判断
...省略...
while (!Thread.interrupted() && !destroyFlag) {
...省略...
  • 我去掉线程睡眠,测试了大约5次,没有再报异常。结果如下gif图。
    在这里插入图片描述

posted on 2022-03-24 18:01  愤怒的苹果ext  阅读(3652)  评论(0编辑  收藏  举报

导航