代码之家  ›  专栏  ›  技术社区  ›  jordan.baucke

Spring WebSockets ActiveMQ convertAndSendToUser

  •  3
  • jordan.baucke  · 技术社区  · 8 年前

    我有一个Spring Boot应用程序(Jhipster),它使用STOMP over WebSockets将信息从服务器传递给用户。

    我最近添加了一个ActiveMQ服务器来处理应用程序的水平扩展,并使用亚马逊自动扩展组/负载平衡器。

    convertAndSendToUser() 方法,该方法在应用程序的单个实例上工作,以定位经过身份验证的用户的“单个队列”,从而仅让他们接收消息。

    然而,当我在负载平衡器后面启动应用程序时,我发现消息 只有 如果事件是在建立websocket代理连接(到代理)的服务器上生成的,是否发送给用户?

    如何确保消息通过ActiveMQ传递到用户实际“也连接”的应用程序的任何实例,而不管哪个实例接收到消息,例如执行 convertAndSendToUser() 事件

    以下是我的StompBrokerRelayMessageHandler供参考:

    @Bean
    public AbstractBrokerMessageHandler stompBrokerRelayMessageHandler() {
        StompBrokerRelayMessageHandler handler = (StompBrokerRelayMessageHandler) super.stompBrokerRelayMessageHandler();
        handler.setTcpClient(new Reactor2TcpClient<>(
            new StompTcpFactory(orgProperties.getAws().getAmazonMq().getStompRelayHost(),
                orgProperties.getAws().getAmazonMq().getStompRelayPort(), orgProperties.getAws().getAmazonMq
                ().getSsl())
        ));
    
        return handler;
    }
    
    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableStompBrokerRelay("/queue", "/topic")
            .setSystemLogin(orgProperties.getAws().getAmazonMq().getStompRelayHostUser())
            .setSystemPasscode(orgProperties.getAws().getAmazonMq().getStompRelayHostPass())
            .setClientLogin(orgProperties.getAws().getAmazonMq().getStompRelayHostUser())
            .setClientPasscode(orgProperties.getAws().getAmazonMq().getStompRelayHostPass());
    
        config.setApplicationDestinationPrefixes("/app");
    }
    

    通过检查 SessionSubscribeEvent ,当用户订阅用户队列时在侦听器中生成,如 simpSessionId

    @Override
    @EventListener({SessionSubscribeEvent.class})
    public void onSessionSubscribeEvent(SessionSubscribeEvent event) {
        log.debug("Session Subscribe Event:" +
            "{}", event.getMessage().getHeaders().toString());
    }
    

    可以在ActiveMQ中找到相应的队列,格式为: {simpDestination}-user{simpSessionId}

    我可以将sessionId保存在一个键值对中,然后将消息推送到该主题频道上吗?


    我也找到了一些 possibilities 在连接/订阅框架中设置ActiveMQ特定的STOMP属性以创建 持久订户 如果我设置了这些属性,会比Spring更了解路由吗?

    client-id & subcriptionName

    1 回复  |  直到 8 年前
        1
  •  3
  •   jordan.baucke    8 年前

    修改 MessageBrokerReigstry config 已解决问题:

    config.enableStompBrokerRelay("/queue", "/topic")
                .setUserDestinationBroadcast("/topic/registry.broadcast")
    

    根据 documentation section 4.4.13 :

    在多应用服务器场景中,用户目标可能会保留 未解析,因为用户连接到其他服务器。在里面 在这种情况下,您可以将目标配置为广播未解决问题 将消息发送给,以便其他服务器有机会尝试。这可能是 通过的userDestinationBroadcast属性完成 Java配置中的MessageBrokerRegistry和 中message broker元素的用户目标广播属性 XML

    我没有看到任何关于“为什么”的文档 /topic/registry.broadcast 是正确的“主题”目的地,但我发现它的各种迭代:

    1. websocket sessions sample doesn't cluster.. spring-session-1.2.2
    2. What is MultiServerUserRegistry in spring websocket?
    3. Spring websocket - sendToUser from a cluster does not work from backup server