从应用程序的其他层发送STOMP消息

时间:2017-11-12 14:40:11

标签: java spring websocket rabbitmq

我正在使用带有RabbitMQ代理的集群tomcat环境中使用Spring Websockets构建应用程序。我有一个API模块需要注册端点来监听。我按照正常的例子提出了这个配置:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer
{
    @Override
    public void configureMessageBroker(final MessageBrokerRegistry config)
    {
        config.enableStompBrokerRelay("/topic/")
            .setRelayHost("localhost")
            .setRelayPort(61613)
            .setClientLogin("guest")
            .setClientPasscode("guest");
    }

    @Override
    public void registerStompEndpoints(final StompEndpointRegistry registry)
    {
        registry.addEndpoint("/updates")
            .setAllowedOrigins("*")
            .withSockJS();
    }
}

虽然这有效,但它并没有解决我的问题,因为看起来WebSocket和中继配置都捆绑在API模块中,因此其他层无法重用代理。我需要在服务层进行stomp消息代理中继配置,以便我们应用程序的其他模块可以将消息推送到RabbitMQ中的主题,然后转向并通知API模块更新所有打开的websockets。

下面是我们的应用程序中相关层的示例图以及我要完成的任务。我需要允许模块" Cron Message Sender"通过我们的其他API模块将消息推送给订阅消息主题的每个人。

Sample Application Layers

2 个答案:

答案 0 :(得分:1)

所以第二种方法确实有效。我将websockets配置为独立运行(没有中继),然后我在服务层建立了一个单独的AMQP消息代理连接,以允许服务之间的通信。在API模块中,我只是听取了AMQP消息代理,然后手动将这些消息转发到通知websocket订阅者的 SimpMessagingTemplate 。我不确定这在技术上是否是“正确”的方式,但它似乎工作得很好,我还没有看到任何实施问题。事实上,我实际上认为我可能更喜欢这种方法,因为我现在只是让我的所有服务能够使用比我最初需要的websockets更多类型的消息来互相交流。

以下是新配置:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer
{
    @Override
    public void configureMessageBroker(final MessageBrokerRegistry config)
    {
        config.enableSimpleBroker("/topic");
    }

    @Override
    public void registerStompEndpoints(final StompEndpointRegistry registry)
    {
        registry.addEndpoint("/updates")
            .setAllowedOrigins("*")
            .withSockJS();
    }
}

这里是我收听消息代理并将消息转发给websocket订阅者的地方:

@Component
public class SendWebSocketUpdates
{
    private static final Logger logger = LoggerFactory.getLogger(SendWebSocketUpdates.class);

    private final Gson gson;

    @Autowired
    private SimpMessagingTemplate messagingTemplate;

    @Autowired
    private MessageBrokerConsumer<String> messageBrokerConsumer;

    public SendWebSocketUpdates()
    {
        this.gson = new Gson();
    }

    @PostConstruct
    public void init()
    {
        //listen for incoming AMQP messages from the rabbitmq server and forward them to the websocket subscribers
        messageBrokerConsumer.addListener((message, topicName) -> {
            final String destination = "/topic/" + topicName;
            final String messageJson = gson.toJson(message.getBody());

            //check to see if trace logging is enabled
            if (logger.isTraceEnabled())
            {
                logger.trace("Sending Message to \"{}\": {}", destination, messageJson);
            }

            //broadcast the via a STOMP message to subscribers of this topic
            messagingTemplate.convertAndSend(destination, messageJson);
        });
    }
}

答案 1 :(得分:-1)

解决此问题很容易。我浪费了一整天的时间来寻找解决方案。 Here 's my answer for the same problem

密钥为setUserDestinationBroadcastsetUserRegistryBroadcast

registry.enableStompBrokerRelay("/topic/", "/queue/", "/exchange/") 
        .setUserDestinationBroadcast("/topic/log-unresolved-user") 
        .setUserRegistryBroadcast("/topic/log-user-registry")