如何使用redis实现发布订阅及遇到的问题
使用背景:
服务A通过接口操作服务B,实现相应逻辑。生产环境上,服务A有两个pod,服务B有3个pod
通过接口调用时,请求只能打到服务B的一个pod上,而我们想要的是服务B的每个pod都能收到服务A发送的请求数据,所以使用redis的发布订阅来实现
实现方法:
1、发送方-服务A
构造需要发送的实体数据objectData
String jsonStr = JSONUtil.toJsonStr(objectData);
使用redisTemplate.convertAndSend("channel_operate",jsonStr);方法像指定的通道"channel_operate"中发送的数据为Object类型
2、接收方-服务B
1)redis配置类中,增加消息监听的逻辑
cpp
/**
* 消息监听
*/
@Bean
public MessageListenerAdapter messageListenerAdapter(RedisSubscriber scriber){
return new MessageListenerAdapter(scriber);
}
/**
* 消息监听容器
*/
@Bean
public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory,MessageListenerAdapter messageListenerAdapter){
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(messageListenerAdapter,new ChannelTopic("channel_operate"));
return container;
}
2)增加订阅到的redis消息类
cpp
@Component
public class RedisSubscriber implements MessageListener {
/**
* 处理接收到的消息
*/
public void onMessage(Message message){
//接收到数据字符串
String valueStr = message.toString();
//去掉数据中的转义字符
StringEscapeUtils.unescapeJava(valueStr);
//如果处理后的数据开头和结尾有多余的字符,使用substring截取你需要的数据即可
//转换为实体对象,JSONUtil是hutool-all包中的工具类
JSONUtil.toBean();
//处理自己的逻辑
......
}
}
代码咔咔写完了,然后就是启动服务测试逻辑了
。。启动报错了。。一个错误是说啥超时,另一个问题就是
java.lang.NoClassDefFoundError: org/springframework/data/redis/connection/SubscriptionListener
提示就是加载SubscriptionListener这个类失败了,找不到,搜一圈之后各种尝试,然后找到了解决办法
说是redis包的问题,项目中用的是
cpp
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
</dependency>
需要改成
cpp
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
</dependency>
再启动就正常了