You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中WebSocket与Stomp内存泄漏问题及解决方法

解决Spring Boot Stomp WebSocket内存泄漏警告

问题原因

警告里提到的MessageBroker-*和clientInboundChannel-*线程,属于Spring WebSocket的Simple消息代理与客户端入站通道线程池。当Web应用停止时,这些线程未被自动销毁,导致Servlet容器(如Tomcat)检测到类加载器无法回收,触发内存泄漏警告。

解决方案

方案1:在配置类中实现销毁逻辑

修改WebSocket配置类,实现DisposableBean接口,在应用上下文销毁时手动停止消息代理和通道线程池:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer, DisposableBean {

    @Autowired
    private SimpleBrokerMessageContainer simpleBrokerMessageContainer;

    @Autowired
    private AbstractMessageChannel clientInboundChannel;

    @Override
    public void configureMessageBroker(final MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/topic");
        registry.setApplicationDestinationPrefixes("/ws");
    }

    @Override
    public void registerStompEndpoints(final StompEndpointRegistry registry) {
        registry.addEndpoint("/our-websocket")
                .setHandshakeHandler(new UserHandshakeHandler())
                .withSockJS();
    }

    @Override
    public void destroy() throws Exception {
        // 停止Simple消息代理
        simpleBrokerMessageContainer.stop();
        // 关闭客户端入站通道的线程池
        if (clientInboundChannel instanceof ExecutorChannel) {
            Executor executor = ((ExecutorChannel) clientInboundChannel).getExecutor();
            if (executor instanceof ExecutorService) {
                ((ExecutorService) executor).shutdown();
                if (!((ExecutorService) executor).awaitTermination(10, TimeUnit.SECONDS)) {
                    ((ExecutorService) executor).shutdownNow();
                }
            }
        }
    }
}

方案2:用SmartLifecycle统一管理组件生命周期

创建独立的生命周期管理类,统一处理WebSocket相关组件的启停:

@Component
public class WebSocketLifecycleManager implements SmartLifecycle {

    private boolean running = false;

    @Autowired
    private SimpleBrokerMessageContainer simpleBrokerMessageContainer;

    @Autowired
    private AbstractMessageChannel clientInboundChannel;
    @Autowired
    private AbstractMessageChannel clientOutboundChannel;

    @Override
    public void start() {
        running = true;
    }

    @Override
    public void stop() {
        // 停止消息代理
        simpleBrokerMessageContainer.stop();
        // 关闭入站、出站通道的线程池
        shutdownChannelExecutor(clientInboundChannel);
        shutdownChannelExecutor(clientOutboundChannel);
        running = false;
    }

    private void shutdownChannelExecutor(AbstractMessageChannel channel) {
        if (channel instanceof ExecutorChannel) {
            Executor executor = ((ExecutorChannel) channel).getExecutor();
            if (executor instanceof ExecutorService) {
                ((ExecutorService) executor).shutdown();
                try {
                    if (!((ExecutorService) executor).awaitTermination(10, TimeUnit.SECONDS)) {
                        ((ExecutorService) executor).shutdownNow();
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }

    @Override
    public boolean isRunning() {
        return running;
    }
}

方案3:升级Spring Boot版本

如果使用的是Spring Boot 2.1.x及更早版本,直接升级到2.2.0及以上版本。后续版本优化了WebSocket组件的生命周期管理,会自动在应用停止时销毁相关线程池,无需手动处理。

内容的提问来源于stack exchange,提问作者Alok Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 01:46:31