使用Spring和sockJS消息丢失websocket

use*_*850 7 spring stomp websocket sockjs spring-websocket

在客户端javascript我有

    stomp.subscribe("/topic/path", function (message) {
        console.info("message received");
    });
Run Code Online (Sandbox Code Playgroud)

在服务器端

public class Controller {
  private final MessageSendingOperations<String> messagingTemplate;
  ?Autowired
  public Controller(MessageSendingOperations<String> messagingTemplate) {
      this.messagingTemplate = messagingTemplate;
  }
  @SubscribeMapping("/topic/path")
  public void subscribe() {
     LOGGER.info("before send");
     messagingTemplate.convertAndSend(/topic/path, "msg");
  }
}
Run Code Online (Sandbox Code Playgroud)

从这个设置,我偶尔(大约30次刷新一次)遇到消息丢失,这意味着我既看不到客户端的"收到消息"消息,也看不到Chrome调试工具的websocket流量.

"发送前"始终记录在服务器端.

当我在subscribe()方法中调用它时,看起来MessageSendingOperations没有准备好.(如果我把Thread.sleep(50);在调用messagingTemplate.convertAndSend之前,问题就会消失(或者不太可能被复制)

我想知道是否有人经历过同样的事情,如果有一个事件可以告诉我MessageSendingOperations是否准备就绪.

Art*_*lan 4

您面临的问题本质上是clientInboundChannel默认ExecutorSubscribableChannel的。

它有3个subscribers

0 = {SimpleBrokerMessageHandler@5276} "SimpleBroker[DefaultSubscriptionRegistry[cache[0 destination(s)], registry[0 sessions]]]"
1 = {UserDestinationMessageHandler@5277} "UserDestinationMessageHandler[DefaultUserDestinationResolver[prefix=/user/]]"
2 = {SimpAnnotationMethodMessageHandler@5278} "SimpAnnotationMethodMessageHandler[prefixes=[/app/]]"
Run Code Online (Sandbox Code Playgroud)

它们是在 内调用的taskExecutor,因此是异步的。

这里的第一个(SimpleBrokerMessageHandler(或StompBrokerRelayMessageHandler)如果您使用的话broker-relay)负责subscription注册topic.

您的messagingTemplate.convertAndSend(/topic/path, "msg")操作可能会在该 WebSocket 会话的订阅注册之前执行,因为它们是在单独的线程中执行的。因此,代理处理程序不知道您将消息发送到会话。

可以@SubscribeMapping在方法上进行配置return,该方法的结果将作为对subscription客户端上该函数的回复发送。

华泰