客户端重新连接时WebSocket消息丢失

时间:2015-05-10 13:17:48

标签: websocket activemq stomp spring-websocket

我在前端使用comment,在后端使用ActiveMQ向客户端发送推送通知。客户端首先使用以下代码订阅主题:

function stompConnect() {
    console.log('STOMP: Attempting connection');
    // recreate the stompClient to use a new WebSocket
    var socket = new SockJS('/websocket');
    var stompClient = Stomp.over(socket);

    stompClient.connect({}, function(frame) {
        stompClient.subscribe('/topic/table-updates', function(notification){
            showNotification(JSON.parse(notification.body));
        });
    }, function (error) {
        console.log('STOMP: ' + error);
        setTimeout(stompConnect, 10000);
        console.log('STOMP: Reconnecting in 10 seconds');
    });
}

stompConnect();

有时底层的websocket连接会丢失,客户端需要重新连接并再次订阅主题(10秒超时)。这导致在客户端重新连接时来自服务器的某些消息丢失。有什么方法可以阻止这种情况吗?

我在后端使用Spring WebSocket。这是配置:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Value("${stomp.port}")
    private Integer stompPort;

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/websocket").withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry
            .enableStompBrokerRelay("/topic/")
            .setRelayPort(stompPort);
    }

    @Bean(initMethod = "start", destroyMethod = "stop")
    public BrokerService brokerService() throws Exception {
        final BrokerService broker = BrokerFactory.createBroker(
            String.format("broker:(vm://localhost,stomp://localhost:%d)?persistent=false", stompPort));

        broker.addShutdownHook(new SpringContextHook());
        return broker;
    }
} 

1 个答案:

答案 0 :(得分:1)

当然可以。

你需要改变一些事情。

这里所有描述都是:Using Queue Browsers to Implement Durable Topic Subscriptions

但我会给你一个简短的概述。

对您的消息传递结构进行了一些重要更改:

  • 将您的websocket消费者订阅到" / queue /"而不是主题和设置队列浏览。
  • 使用Reliable Messaging
  • 从您的制作人发送消息

这是一个基本的例子:

  1. 用户打开网页,订阅序列号为-1的队列浏览/ queue / important-stuff(仅限新消息)。
  2. 对于到达的每条消息,将其序列号存储在某处。而用户可以在消息中获得重要数据。
  3. 用户的websocket连接丢失。
  4. 检测并重新连接,请务必使用杰夫的示例here作为参考,网络套接字只能打开一次。
  5. 重新订阅并传入from-seq标题中存储的序列号。
  6. Apollo经纪人将发送丢失的消息。
  7. 请记住,经纪人可能会因为您需要遵循网页上的建议而被堵塞的消息被堵塞:

    • 使用到期时间将消息发送到队列,以便在到达到期时间后自动删除。
    • 定期运行一个普通的消费者应用程序,它可以游标 队列和删除消息被认为不再需要。