【问题标题】:Multiple user sessions not receiving subscription message - spring stomp websocket多个用户会话未收到订阅消息 - spring stomp websocket
【发布时间】:2018-10-18 18:55:46
【问题描述】:

我正在使用 Spring stomp websocket 框架向客户端发送订阅消息。我们使用 ActiveMQ 作为消息代理 并且正在使用 stomp javascript 客户端。 Spring 4.1.5 和在这个架构中,消息是使用

发送的
simplemessagingTemplate.convertAndSendToUser(user, "/queue/msg", serverMsg, map);

为了确保只有正确的用户才能收到他们的消息,我还使用了实现 ChannelInterceptor 的 QueueSubscriptionInterceptor。 消息正确地传递到目的地。像这样使用JS客户端接收消息。

  stompClient.subscribe('/user/guest/queue/msg', function(greeting){              
                    x = JSON.parse(greeting.body);
                    ...
                    }

到目前为止一切顺利。但是,当有多个用户会话时,只有一个会话接收到消息。对于(例如),如果两个“访客”用户 已登录,我希望所有两个“访客”用户都能收到消息。这似乎没有发生。看着日志, 我看到消息似乎已发送..

2015-04-11 14:39:40 DEBUG StompBrokerRelayMessageHandler:738 - Forwarding SEND /queue/msg-user1 session=_system_ application/json;charset=UTF-8 payload={"my message to you...)
2015-04-11 14:39:40 DEBUG StompBrokerRelayMessageHandler:738 - Forwarding SEND /queue/msg-user0 session=_system_ application/json;charset=UTF-8 payload={"my message to you...)

我看到只有一个客户端接收到消息,而没有看到另一个。阅读 Spring 文档,我知道这是默认行为。 谁能告诉我我做错了什么。

谢谢。

【问题讨论】:

    标签: spring activemq stomp spring-websocket


    【解决方案1】:

    您应该使用主题的语义而不是队列。

    队列允许消息被消费一次,但主题允许每个订阅者消费一次。所以像 /topic/user/guest/msg 这样的东西可能会这样做。

    【讨论】:

    • 我尝试更改为主题而不是队列。仍然无法让它工作。日志显示如下:翻译的 /user/guest/topic/msg -> [/topic/msg-user2, /topic/msg-user3]。使用 convertAndSendToUser 会自动附加 /user/ 从而创建 /user/guest/topic/msg。
    【解决方案2】:

    在连接帧中设置确认头。这将做的是服务器将继续向您发送相同的消息,直到您发送回一个 ack 帧。我在下面通过在收到消息后立即调用 greeting.ack() 来执行此操作。将其设置为“client-individual”意味着服务器必须从特定客户端的所有会话中接收 ack,否则它将在每个 CONNECT 上继续重新发送相同的 msg。 希望这可以帮助!! 使用下面的代码作为参考。

       function connect() {
        var socket = new SockJS('/powerme-notification-websocket');
        stompClient = Stomp.over(socket);
        stompClient.connect(
            {client_id:'testClient'}, function (frame) {
            setConnected(true);
            console.log('Connected: ' + frame);
            stompClient.subscribe('/user/topic/releaseLock', function (greeting) {
            stompClient.subscribe('/queue/releaseLock-testClient', function (greeting) {
                console.log(greeting);
                showGreeting(greeting.body);
                greeting.ack();
            },{durable:true,
                'auto-delete':false,
            ack:'client-individual',
            id:'testClient'});
    
        }); 
    }
    

    参考资料: https://stomp.github.io/stomp-specification-1.2.html#ACK

    【讨论】:

    • 对于通过 websocket 进行的通信,我们使用 STOMP 协议。就像 http 协议有 put、post、get 等一样,STOMP 有 connect、subscribe、ack 等,它们被称为帧。我们发送的第一帧是连接帧,它告诉服务器我们使用标头定义的连接参数。 ack 标头告诉服务器它必须从客户端接收消息传递的 ack。如果服务器没有收到消息的 ack 帧,它将在每次 CONNECT 时将其重新发送给客户端。
    猜你喜欢
    • 2019-02-14
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 2020-01-07
    • 2016-11-09
    • 1970-01-01
    • 2015-06-23
    相关资源
    最近更新 更多