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

STOMP连接因心跳丢失关闭:前端有Ping-Pong仍报错求助

STOMP + ActiveMQ Artemis WebSocket连接超时问题(AMQ229014错误)

错误日志

Received ERROR {message=[AMQ229014: Did not receive data from /192.0.2.1:46748 within the 20000ms connection TTL. The connection will now be closed.]} session=rgmekuxj

环境配置

  • 前端:使用SockJS和Stomp.js,浏览器控制台可见Ping-Pong交互,确认客户端已发送心跳。
  • 后端:Spring Boot,配置StompBrokerRelayMessageHandler设置心跳间隔:
public void configureMessageBroker(MessageBrokerRegistry config) {
    int sendInterval = 10000; // 发送间隔(毫秒)
    int receiveInterval = (int) (sendInterval * heartBeatReceiveScale);
    config.setApplicationDestinationPrefixes("/app");
    config.enableStompBrokerRelay("/topic", "/queue")
            .setUserDestinationBroadcast("/topic/random")
            .setUserRegistryBroadcast("/topic/simp-user-registry")
            .setTcpClient(createTcpClient())
            .setSystemLogin(username)
            .setSystemPasscode(password)
            .setClientLogin(username)
            .setClientPasscode(password)
            .setSystemHeartbeatSendInterval(sendInterval) // 设置系统心跳发送间隔
            .setSystemHeartbeatReceiveInterval(receiveInterval);
}

后端日志片段:

2024-11-29T DEBUG 40756 --- [NotificationService] [ent-scheduler-5]
o.s.m.s.s.StompBrokerRelayMessageHandler : Received CONNECTED heart-beat=[10000, 10000] session=itwv0lto

2024-11-29T DEBUG 13048 --- [NotificationService] [MessageBroker-6]
o.s.m.s.s.StompBrokerRelayMessageHandler : Forwarding SEND /topic/simp-user-registry session=_system_ application/json payload={...}

此外,使用自定义ReactorNettyTcpClient处理Broker连接及故障转移重试逻辑。

观察结果

  • 前端控制台显示Ping-Pong交互,心跳已发送。
  • 后端日志显示CONNECTED帧指定heart-beat=[10000, 10000]。

但连接仍在20秒TTL超时后被关闭。

问题

  1. 如何确认后端是否正确接收到心跳?
  2. ActiveMQ Artemis或Spring Boot中是否有特定配置需调整以解决该问题?

解决方案

1. 确认后端是否接收心跳的方法

  • 开启TRACE级日志:
    在Spring Boot配置文件中,将STOMP和Artemis相关日志级别设为TRACE,可查看心跳帧的收发细节:

    logging:
      level:
        org.springframework.messaging.simp.stomp: TRACE
        org.apache.activemq.artemis.core.protocol.stomp: TRACE
    

    若日志中出现Received STOMP PING或Sending STOMP PING条目,说明心跳正常收发;若只有发送记录无接收记录,说明心跳在传输中丢失或未被正确转发。

  • 抓包验证:
    使用Wireshark或tcpdump抓取前端到Spring Boot、Spring Boot到Artemis的TCP数据包,检查是否有STOMP心跳帧(空帧,仅含\n\n)传输。

2. 配置调整建议

Spring Boot端调整

  • 配置客户端与Spring Boot的心跳:
    当前仅设置了Spring Boot与Broker的systemHeartbeat,需额外配置客户端与Spring Boot之间的心跳:

    @Override
    public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
        registration.setHeartbeatTime(10000, 10000); // 客户端与Spring Boot的心跳间隔
        registration.setSendTimeLimit(10000)
                    .setSendBufferSizeLimit(512 * 1024)
                    .setTimeToFirstMessage(30000);
    }
    

    确保各层级心跳间隔匹配,避免中间层未转发心跳。

  • 检查自定义TcpClient的心跳处理:
    自定义ReactorNettyTcpClient需确保不过滤STOMP空心跳帧,可添加如下处理:

    private ReactorNettyTcpClient<byte[]> createTcpClient() {
        return new ReactorNettyTcpClient<>(
            client -> client.host("broker-host").port(61613)
                            .handle((inbound, outbound) -> {
                                inbound.receive().subscribe();
                                return outbound.send(inbound.receive()).then();
                            }),
            new StompReactorNettyCodec()
        );
    }
    

ActiveMQ Artemis端调整

  • 调整连接TTL与心跳的匹配关系:
    Artemis默认connection-ttl为20000ms,需将其设为心跳间隔的2-3倍,避免网络延迟导致误判。修改broker.xml的STOMP acceptor:

    <acceptor name="stomp-acceptor">tcp://0.0.0.0:61613?protocols=STOMP;connectionTtl=30000</acceptor>
    
  • 启用STOMP心跳支持:
    在STOMP acceptor配置中添加stompHeartBeatSupport=true,强制Artemis处理STOMP心跳:

    <acceptor name="stomp-acceptor">tcp://0.0.0.0:61613?protocols=STOMP;connectionTtl=30000;stompHeartBeatSupport=true</acceptor>
    

内容的提问来源于stack exchange,提问作者abhishek yadav

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 00:41:10