spring taskExecutor redis redisMessageListenerContailner jvm 线程优化

本文介绍了一位测试工程师在进行系统压力测试时遇到的问题:由于Redis消息监听容器(redisMessageListenerContainer)未合理配置线程池,导致系统进程中产生了大量线程并最终被杀掉。文章详细分析了redisMessageListenerContainer的工作原理,并给出了通过配置自定义线程池来解决问题的具体方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景:

测试工程师给系统做压力测试,发现JVM产生了大量的redisMessageListenerContainer线程,系统跑着跑着进程就被kill掉了


查看源码:

进入redisMessageListenerContainer 类打断点进去,查看内部代码

redisMessageListenerContainer.java

public void onMessage(Message message, byte[] pattern) {
		Collection<MessageListener> listeners = null;
		// if it's a pattern, disregard channel
		if (pattern != null && pattern.length > 0) {
			listeners = patternMapping.get(new ByteArrayWrapper(pattern));
		} else {
			pattern = null;
			// do channel matching first
			listeners = channelMapping.get(new ByteArrayWrapper(message.getChannel()));
		}
		if (!CollectionUtils.isEmpty(listeners)) {
			dispatchMessage(listeners, message, pattern);
		}
	}

}

	private void dispatchMessage(Collection<MessageListener> listeners, final Message message, final byte[] pattern) {
		final byte[] source = (pattern != null ? pattern.clone() : message.getChannel());
		for (final MessageListener messageListener : listeners) {
			taskExecutor.execute(new Runnable() {// 使用了线程池

				public void run() {
					processMessage(messageListener, message, source);
				}
			});
		}
	}

	// 测试工程师给系统做压力测试,发现JVM产生了大量的redisMessageListenerContainer线程,系统跑着跑着进程就被kill掉了
	public void afterPropertiesSet() {
		if (taskExecutor == null) {// 如果没有设置默认的使用的是SimpleAsyncaskExecutor,这是一个简单的执行器,并不有线程池功能
			manageExecutor = true;
			taskExecutor = createDefaultTaskExecutor();
		}
		if (subscriptionExecutor == null) {
			subscriptionExecutor = taskExecutor;
		}
		initialized = true;
	}

	protected TaskExecutor createDefaultTaskExecutor() {
		String threadNamePrefix = (beanName != null ? beanName + "-" : DEFAULT_THREAD_NAME_PREFIX);
		return new SimpleAsyncTaskExecutor(threadNamePrefix);
	}

RedisHttpSessionConfiguration.Java

    @Bean
    public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory, RedisOperationsSessionRepository messageListener) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        if(this.redisTaskExecutor != null) {
            container.setTaskExecutor(this.redisTaskExecutor);
        }

        if(this.redisSubscriptionExecutor != null) {
            container.setSubscriptionExecutor(this.redisSubscriptionExecutor);
        }

        container.addMessageListener(messageListener, Arrays.asList(new PatternTopic[]{new PatternTopic("__keyevent@*:del"), new PatternTopic("__keyevent@*:expired")}));
        container.addMessageListener(messageListener, Arrays.asList(new PatternTopic[]{new PatternTopic(messageListener.getSessionCreatedChannelPrefix() + "*")}));
        return container;
    }
    
    @Qualifier("springSessionRedisTaskExecutor")
    public void setRedisTaskExecutor(Executor redisTaskExecutor) {
        this.redisTaskExecutor = redisTaskExecutor;
    }

解决方案:

XML中添加一个redis线程池,问题解决

<bean id="springSessionRedisTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
		<!-- 核心线程数 -->
		<property name="corePoolSize" value="10" />
		<!-- 最大线程数 -->
		<property name="maxPoolSize" value="300" />
		<!-- 队列最大长度 -->
		<property name="queueCapacity" value="500" />
		<!-- 线程池维护线程所允许的空闲时间,默认为60s -->
		<property name="keepAliveSeconds" value="60" />
</bean>


<think>好的,我现在要帮助用户了解在Spring Boot后端实现高并发处理以及确保线程安全的方法。首先,我需要整理用户提供的引用内容,看看有哪些现有的信息可以利用。 用户提到了几个引用,其中引用[3]提到异步处理、线程池、缓存、数据库连接池和限流。引用[1]讨论了线程安全的技术手段,如同步机制、线程安全的集合类和ThreadLocal。引用[4]介绍了Spring Boot 3的虚拟线程,引用[5]提到了消息队列。我需要将这些点整合起来,形成一个结构清晰的回答。 首先,我应该分点回答,可能包括线程安全策略和高并发处理方案。线程安全方面,同步机制、线程安全集合、ThreadLocal、无状态设计和并发测试都是关键点。高并发处理则涉及异步处理、虚拟线程、连接池优化、缓存、限流降级、消息队列、水平扩展和监控。 接下来要确保每个部分都有对应的引用支持。例如,虚拟线程部分引用[4],异步处理引用[3]和[5],线程池引用[3],消息队列引用[5]。需要正确标注引用编号,避免混淆。 同时,用户可能需要具体的示例或代码片段,比如如何配置线程池或使用@Async注解。还要注意使用中文,LaTeX格式的正确应用,以及生成相关问题。 需要检查是否有遗漏的最佳实践,比如数据库连接池的配置,HikariCP的推荐,以及分布式限流工具如Sentinel。此外,虚拟线程Spring Boot 3的新特性,应该强调其优势和应用场景。 最后,生成的相关问题需要覆盖用户可能进一步询问的方向,比如虚拟线程的原理、ThreadLocal的注意事项、限流算法选择、消息队列对比、无状态设计实现和性能测试工具。 确保回答结构清晰,步骤明确,引用正确,并且语言自然流畅,符合用户的要求。</think>以下是在Spring Boot中实现高并发处理与保障线程安全的系统性解决方案,结合最新技术特性与实践经验整理: ### 一、线程安全保障策略 1. **同步机制选择** - 使用`ReentrantLock`实现细粒度控制:比`synchronized`更灵活,支持公平锁/非公平锁 ```java private final Lock lock = new ReentrantLock(); public void safeMethod() { lock.lock(); try { // 临界区操作 } finally { lock.unlock(); } } ``` - `StampedLock`优化读多写少场景:实现乐观读锁(JDK8+) 2. **线程安全容器** - 并发集合类:`ConcurrentHashMap`(分段锁优化)、`CopyOnWriteArrayList`(写时复制) - 原子类操作:`AtomicInteger`使用CAS机制,性能比同步块高5-10倍[^1] 3. **ThreadLocal应用规范** - 适用于请求上下文、事务管理等场景 - 必须配套`remove()`清理,防止内存泄漏(尤其在Tomcat线程池中) 4. **无状态设计原则** - 控制器层避免实例变量 - 服务层推荐使用原型(prototype)作用域 5. **并发测试验证** - 使用JMeter进行压测 - 结合`@RepeatedTest`编写并发单元测试 ### 二、高并发处理方案 1. **异步处理体系** - 注解驱动:`@Async`配合自定义线程池 ```java @Configuration @EnableAsync public class AsyncConfig { @Bean(name = "taskExecutor") public Executor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); executor.setMaxPoolSize(50); executor.setQueueCapacity(200); executor.setThreadNamePrefix("Async-"); executor.initialize(); return executor; } } ``` 2. **虚拟线程实践(Spring Boot 3+)** - 配置参数:`spring.threads.virtual.enabled=true` - 单节点支持10万+并发请求,吞吐量提升300%[^4] ```java @Bean TaskExecutor virtualThreadExecutor() { return new SimpleAsyncTaskExecutor.Builder() .virtualThreads(true) .threadNamePrefix("VT-").build(); } ``` 3. **连接池优化** - HikariCP推荐配置: ```yaml spring.datasource.hikari: maximum-pool-size: 20 minimum-idle: 5 connection-timeout: 3000 idle-timeout: 600000 max-lifetime: 1800000 ``` 4. **缓存策略分层** - L1缓存:Caffeine(命中率95%+) - L2缓存:Redis集群(TPS 10万+) 5. **限流与降级** - Sentinel动态规则配置: ```java @PostConstruct public void initFlowRules(){ List<FlowRule> rules = new ArrayList<>(); FlowRule rule = new FlowRule(); rule.setResource("protectedResource"); rule.setGrade(RuleConstant.FLOW_GRADE_QPS); rule.setCount(1000); // 阈值 rules.add(rule); FlowRuleManager.loadRules(rules); } ``` 6. **消息队列解耦** - Kafka分区策略优化:提升并行消费能力 - RabbitMQ确认模式:`publisher confirms`保障可靠性 ### 三、性能提升实践 1. **水平扩展方案** - Kubernetes + Spring Cloud Gateway实现自动伸缩 - 服务注册发现:Consul/Nacos集群部署 2. **监控体系构建** - Prometheus + Grafana监控看板 - 关键指标: - 线程池活跃度:`thread_pool_active_threads` - 请求吞吐量:`http_server_requests_seconds_count` - GC频率:`jvm_gc_pause_seconds_sum` 3. **JVM调优参数** ```bash -XX:+UseZGC -Xmx4g -Xms4g -XX:MaxMetaspaceSize=512m ``` $$T_{throughput} = \frac{N_{requests}}{t_{response}} \times C_{concurrency}$$ 其中$C_{concurrency}$表示并发系数,与CPU核心数和IO等待时间正相关[^3]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值