带有Artemis 2.6.3的Spring WebSocketMessageBrokerConfigurer组播(主题)不起作用

时间:2018-09-30 09:42:53

标签: spring-boot websocket spring-websocket stomp activemq-artemis

Artemis mutilcast地址和队列没有预期的行为。 我的想法是为可以有多个websocket会话(web,android等)的用户创建组或特定的消息传递。服务器将向artemis多播地址发布通知,所有订阅者都应收到该通知。在当前场景中,我只是强制用户'luislaves00'并创建多个会话。在artemis中,我可以看到2个使用者(不确定spring的Message Broker Relay的工作方式),但是这些使用者的行为就像是循环机制,而不是发布者-订阅者。使用Spring中的内存代理,它可以正常工作,但并不持久,因此,在没有订阅者连接的情况下,消息将被丢弃。 这是我正在使用的代码:

客户端部分:

function connect() {
    var socket = new SockJS('/notification-websocket');
    stompClient = Stomp.over(socket);
    var headers = {
        // todo: server will handle this logic
        'client-id': 'luisalves00',
        'durable-subscription-name': 'luisalves00',
        'id' : 'luisalves00'
    };
    stompClient.connect(headers, function(frame) {
        setConnected(true);
        console.log('Connected: ' + frame);
        // todo: server will handle this logic
        stompClient.subscribe('/topic/notification/username' + 'luisalves00', function(notification) {
            showNotification(JSON.parse(notification.body).content);
        }, headers);
    });
}

经纪人中继配置:

public void configureMessageBroker(MessageBrokerRegistry config) {
        // Artemis ->
        // tcp://0.0.0.0:61613?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=STOMP;useEpoll=true
        config.enableStompBrokerRelay("/topic").setRelayHost("127.0.0.1").setRelayPort(61613);
        config.setApplicationDestinationPrefixes("/app");
        //config.enableSimpleBroker("/topic");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {

        logger.info("Registering the stomp endpoints.");

        registry.addEndpoint("/notification-websocket").setAllowedOrigins("*").withSockJS();

    }

服务器虚拟通知生成器:

@Scheduled(fixedDelay = 20000)
public void scheduleTaskWithFixedDelay() {
    final Notification message = new Notification(UUID.randomUUID().toString() + " -> "  + dateTimeFormatter.format(LocalDateTime.now()));
    try {
        final String user = "luisalves00";
        logger.info("Creating msg={}", message);
        final Map<String, Object> headers = new HashMap<>();
        headers.put("subscription-id", user);
        template.convertAndSend("/topic/notification/username/" + user, message, headers);
    } catch (Exception e) {
        logger.error("", e);
    }
}

当客户订阅时,artemis使用以下参数创建地址和持久队列:

Addesses: 
id=2147496008 name=/topic/notification/group1/ routingType=[MULTICAST] queueCount=1

Queue
id=2147496011 
name=group1.group1 
address=/topic/notification/group1/ 
routingType=MULTICAST
durable=true
maxConsumers-1
purgeOnNoConsumers=false 
consumerCount=0

1 个答案:

答案 0 :(得分:0)

要进行耐久的工作,您必须使用:

'client-id': '<some unique identifier for each client>'
'durable-subscription-name': 'tech-news'

对于我的实现,我停止使用持久性,因为通知的想法将在创建时传递(低延迟)。如果使用者未连接,则可以连接到历史数据库以获取他在连接时未收到的旧消息。 如果您真的想使其持久,我建议在服务器端为连接的用户处理“客户端ID”和“持久订阅名称”。如果用户没有正在进行的会话,则创建一个持久队列。他创建的下一个会话应该是不持久的,因为他们将收到与持久会话相同的消息。如果第一个会话死亡,他仍然会在其他会话上收到消息。当所有人都死了并且重新连接时,它将再次成为第一个会话,他将收到所有未在持久队列中传递的消息(可能是他已经在非持久队列中接收的某些消息),但是他将拥有所有邮件(如我之前所说,应该以其他方式处理)。