springboot2+redis 订阅发布,解决接收消息累计线程到内存溢出,使用自定义线程池接收消息

pom 添加redis

java 复制代码
		<!-- redis 缓存操作 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>

发布消息

java 复制代码
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

/**
 * @author zpy
 * @date 2023/8/9 13:48
 */
@Slf4j
@Component
public class RedisMessageUtils {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 向通道发布消息
      * topic 通道名称
     */
    public void sendMessage(String topic, Object message) {
        if (!StringUtils.hasText(topic)) {
            return;
        }
        try {
            stringRedisTemplate.convertAndSend(topic, message);
            log.info("发送消息成功,topic:{},message:{}", topic, message);
        } catch (Exception e) {
            log.info("发送消息失败,topic:{},message:{}", topic, message);
            e.printStackTrace();
        }
    }

}

接收消息

java 复制代码
    /**
     * Redis消息监听器容器
     * 这个容器加载了RedisConnectionFactory和消息监听器
     * 可添加多个不同话题的redis监听器,需要将消息监听器和消息频道绑定,
     * 通过反射调用消息订阅处理器的相关方法进行业务处理
     *
     * @param  redisConnectionFactory   	连接工厂
     * @param  listener                 	Redis消息监听器
     * @param  MessageListenerAdapter   	Redis消息监听适配器
     * @return RedisMessageListenerContainer    消息监听容器
     */
    @Bean
    @SuppressWarnings("all")
    public RedisMessageListenerContainer container(RedisMessageListener listener) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactorySlave());
        // 所有的订阅消息,都需要在这里进行注册绑定
        // new PatternTopic(TOPIC_NAME1) 表示发布信息的频道
        // 可以添加多个频道以及配置不同的频道
        container.addMessageListener(listener, new PatternTopic("消息频道名称"));
        //container.addMessageListener(adapter, new PatternTopic(SystemConstants.TOPIC_NAME2));
        container.setTaskExecutor(springSessionRedisTaskExecutor());

        /**
         * 设置序列化对象
         * 特别注意:1. 发布的时候和订阅方都需要设置序列化
         *         2. 设置序列化对象必须放在 {加入消息监听器} 这步后面,不然接收器接收不到消息
         */
		/*Jackson2JsonRedisSerializer seria = new Jackson2JsonRedisSerializer(Object.class);
		ObjectMapper objectMapper = new ObjectMapper();
		objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
		objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
		seria.setObjectMapper(objectMapper);
		container.setTopicSerializer(seria);*/
        return container;
    }

/** 自定义接收消息的线程池
*/
    @Bean
    public ThreadPoolTaskExecutor springSessionRedisTaskExecutor() {
        ThreadPoolTaskExecutor springSessionRedisTaskExecutor = new ThreadPoolTaskExecutor();
        springSessionRedisTaskExecutor.setCorePoolSize(8);
        springSessionRedisTaskExecutor.setMaxPoolSize(15);
        springSessionRedisTaskExecutor.setKeepAliveSeconds(10);
        springSessionRedisTaskExecutor.setQueueCapacity(1000);
        springSessionRedisTaskExecutor.setThreadNamePrefix("redis-");
        return springSessionRedisTaskExecutor;
    }

测试

java 复制代码
@Scheduled(cron = "0/10 * * * * *")
	private void init(){

		for(int i=0;i<50;i++){
			//处理请求
			redisMessageUtils.sendMessage("接收频道名称", UUID.randomUUID().toString());
		}
	}
相关推荐
洛小豆1 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学2 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole2 小时前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端
华仔啊2 小时前
基于 RuoYi-Vue 轻松实现单用户登录功能,亲测有效
java·vue.js·后端
程序员鱼皮3 小时前
刚刚 Java 25 炸裂发布!让 Java 再次伟大
java·javascript·计算机·程序员·编程·开发·代码
浮游本尊3 小时前
Java学习第21天 - 微服务架构设计
java
渣哥3 小时前
Java CyclicBarrier 详解:原理、使用方式与应用场景
java
杨杨杨大侠3 小时前
打开 JVM 黑匣子——走进 Java 字节码(一)
java·jvm·agent
SimonKing3 小时前
接口调用总失败?试试Spring官方重试框架Spring-Retry
java·后端·程序员