首页 > 解决方案 > Spring-data-redis Jedis RedisMessageListenerContainer - 发生连接失败。5000毫秒后重启订阅任务

问题描述

我在这里发现了一些类似的问题,但解决方案并没有解决我的问题,我的消息侦听器(订阅)配置似乎有错误。

我对 redis 很陌生,我想列出/读取/订阅没有任何密码的现有 redis 服务器。

我可以通过本地的 redis-cli 收听该服务器,但是当我尝试将 redis 侦听器添加到我的 Spring Boot 应用程序时,消息侦听器容器似乎无法建立连接。

我收到此重复消息:

2021-01-18 22:12:32 [redisContainer-31] ERROR o.s.d.r.l.RedisMessageListenerContainer -Connection failure occurred. Restarting subscription task after 5000 ms

下面是一些关于我如何将spring-data-redis (2.3.3.RELEASE)+ jedis (2.10.0)spring boot 添加到我的应用程序的片段。

pom.xml

  ...
  <properties>
    ...
    <redis.version>2.3.3.RELEASE</redis.version>
    <jedis.version>2.10.0</jedis.version>
  </properties>

  <dependencies>
    ...  
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
      <version>${redis.version}</version>
    </dependency>
    <!-- There is no redis.clients.util.SafeEncoder class definition in version 3.1.0 -->
    <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>${jedis.version}</version>
    </dependency>
  </dependencies>
  ...

应用程序属性

# Redis
spring.redis.database=0
spring.redis.host=sabong-dev.abs3252.8888.use69.cache.amazonaws.com
spring.redis.port=6379
spring.redis.password=
spring.redis.timeout=60000
spring.redis.channel.sabongEvents=SABONG_EVENTS

请注意,连接到现有的 redis 服务器没有密码,我可以在SABONG_EVENTS本地使用redis-cli.

RedisConfig.java

@Configuration
public class RedisConfig {

    @Value("${spring.redis.host}")
    private String redisHost;

    @Value("${spring.redis.port}")
    private Integer redisPort;

    @Value("${spring.redis.channel.sabongEvents}")
    private String channelTopic;

    @Bean
    JedisConnectionFactory jedisConnectionFactory() {
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(redisHost, redisPort);
        return new JedisConnectionFactory(redisStandaloneConfiguration);
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(jedisConnectionFactory());
        return template;
    }

    @Bean
    MessageListenerAdapter messageListener() {
        return new MessageListenerAdapter(new MyRedisMessageSubscriber());
    }

    @Bean
    RedisMessageListenerContainer redisContainer() {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(jedisConnectionFactory());
        container.addMessageListener(messageListener(), channelTopic());
        return container;
    }

    @Bean
    ChannelTopic channelTopic() {
        return new ChannelTopic(channelTopic);
    }

}

MyRedisMessageSubscriber.java

package package.my.sample;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Service;

...

@Service
public class RedisMessageSubscriber implements MessageListener {

    private static final Logger logger = LoggerFactory.getLogger(MyRedisMessageSubscriber.class);

    public void onMessage(Message message, byte[] pattern) {
        String msg = message.toString();
        logger.info("\n[topic-message]: {}\n", msg);
    }

}

我不确定我的代码有什么问题,我知道这很简单,因为我只想显示 sysout/logger.info 我从 redis 频道获得的消息。

应用程序运行但无法建立连接以进行读取/侦听。

我可能在这里遗漏了一些代码或配置,但我不确定在哪里或什么。

谢谢!

更新(解决方案) 似乎spring-boot没有自动设置我的redis主机和端口,可能是因为我错过了一些东西或一些错误的属性名称导致它没有自动设置。

在我的 redis 配置类中,我在JedisConnectionFactoryusing中设置了 redis 主机和端口RedisStandaloneConfiguration。由于我的问题只是建立与我的消息侦听器容器的连接.. 它能够使用此示例与我的外部 redis 服务器建立连接。

我没有删除这篇文章,而是用答案更新了它,因为我知道我可能会再次需要这个,因为我很健忘:)

标签: javaspring-bootredisspring-data-redisjedis

解决方案


After debugging, I found out that my configuration properties seems not to work

spring.redis.host=sabong-dev.abs3252.8888.use69.cache.amazonaws.com
spring.redis.port=6379

I was expecting that spring boot will set these properties values for me. As I debugged, the JedisConnectionFactory is still pointing to localhost and 6379. No problem with the port since it is the same value as what I am expecting, but localhost seems to be the default value not the one I set or expected.

So inorder to set the host/port since JedisConnectionFactory.setHost(host) and JedisConnectionFactory.setPort(port) are deprecated, I use RedisStandaloneConfiguration to set both host and port and use this in the constructor of JedisConnectionFactory. So it will look like this.

RedisConfig.java

...
@Value("${spring.redis.host}")
private String redisHost;

@Value("${spring.redis.port}")
private Integer redisPort;

@Value("${spring.redis.channel.sabongEvents}")
private String channelTopic;
...

@Bean
JedisConnectionFactory jedisConnectionFactory() {
    RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(redisHost, redisPort);
    return new JedisConnectionFactory(redisStandaloneConfiguration);
}

After setting the correct host (and port), it was able to establish a connection to my redis server and channel.

Again, my issue is my message listener container is having a connection problem and the main problem was... my redis host and port was not set automatically by spring-boot. I know there might be some mistakes to my properties causing spring-boot not to set it properly. But the idea is, once I set both redis host and port, I was able to connect to my server, and I was able to read/listen to my set channel.

I will update my original post and fix the code


推荐阅读