【问题标题】:WebSocket messages are lost while client is reconnecting客户端重新连接时 WebSocket 消息丢失
【发布时间】:2015-07-21 00:36:41
【问题描述】:

我在前端使用STOMP.js,在后端使用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;
    }
} 

【问题讨论】:

  • 检查是否可以配置 STOMP 客户端库以创建在 ActiveMQ STOMP page 上定义的持久订阅者

标签: websocket activemq stomp spring-websocket


【解决方案1】:

当然可以。

你需要改变一些东西。

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

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

消息结构的一些重要变化:

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

这是一个基本的例子:

  1. 用户打开网页并订阅 /queue/important-stuff,队列浏览序列号为 -1(仅限新消息)。
  2. 对于每条到达的消息,将其序列号存储在某处。同时用户在消息中享受他们的重要数据。
  3. 用户的 websocket 连接断开。
  4. 检测到这个并重新连接,一定要用Jeff的例子here作为参考,web sockets只能打开一次。
  5. 重新订阅并在 from-seq 标头中传入存储的序列号。
  6. Apollo 代理将发送丢失的消息。

请记住,代理可能会被一些消息阻塞,您需要遵循页面上的建议,并且:

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

【讨论】:

  • 您好,您找到解决方案了吗?我有一个类似的问题。虽然消息是从服务器推送的,但有时客户端会错过它。我使用的是队列而不是主题
  • 我也有类似的问题,还在寻找解决办法
猜你喜欢
  • 2015-08-17
  • 2015-01-17
  • 2019-02-20
  • 1970-01-01
  • 1970-01-01
  • 2020-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多