springspring-bootwebsocketactivemq-artemisspring-websocket

STOMP Connection Closes Due to Missing Heartbeats Despite Frontend Showing Ping-Pongs


I'm facing a connection issue with my WebSocket setup using STOMP and ActiveMQ Artemis. The error message I receive in my logs:

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

Setup:

public void configureMessageBroker(MessageBrokerRegistry config) {
    int sendInterval = 10000; // Send interval in milliseconds
    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) // Set heartbeat send interval
            .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={...}

Additionally, I am using a custom ReactorNettyTcpClient for broker connections and retry logic for failovers.

Observations:

Despite this, the connection closes after the TTL timeout (20 seconds).

Questions:


Solution

  • Solution

    The solution involves adjusting the heartBeatToConnectionTtlModifier parameter in your STOMP acceptor configuration in broker.xml. This parameter controls how the broker interprets client heartbeats in relation to connection timeouts.

    Implementation

    Modify your STOMP acceptor configuration in broker.xml as follows:

    <!-- STOMP Acceptor -->
    <acceptor name="stomp">tcp://0.0.0.0:61613?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=STOMP;useEpoll=true;heartBeatToConnectionTtlModifier=10.0</acceptor>
    

    Explanation

    heartBeatToConnectionTtlModifier: This parameter determines how the broker calculates the connection timeout based on the client's heartbeat settings.

    Default value is typically 2.0

    Increasing it to 10.0 makes the broker more lenient with heartbeat timing

    The formula is: connectionTTL = heartBeatToConnectionTtlModifier * max(clientHeartBeatSendFrequency, clientHeartBeatReceiveFrequency)