WebSocket 消息并非始终传递

WebSocket messages are not delivered all the times

我有一个使用 WebSockets 的应用程序,使用 spring-boot 应用程序作为后端,Stomp/SockJS 在客户端,spring-boot 应用程序使用 JMS 队列消息并通知更改给正确的用户。问题是什么?有时有效,有时无效,相同的代码和用户可能有效或无效。

客户端代码有点难以复制到这里,因为它集成在 react/redux 应用程序上,但基本上是对两个不同频道的订阅,都在 Spring 的配置中定义。会话是根据调试信息正确创建的,但有时会处理消息以将其发送到连接的会话。

这是 Spring 的配置 class。

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {

   @Override
   public void registerStompEndpoints(StompEndpointRegistry registry) {

      registry
         .addEndpoint("/stomp")
         .setAllowedOrigins("*")
         .withSockJS();
   }

   public void configureMessageBroker(MessageBrokerRegistry registry) {

      registry
         .setApplicationDestinationPrefixes("/app")
         .enableSimpleBroker("/xxxx/yyyy", "/ccccc");
   }

   @Override
   public void configureClientInboundChannel(ChannelRegistration registration) {

      registration.interceptors(new ChannelInterceptor() {

         @Override
         public Message<?> preSend(Message<?> message, MessageChannel channel) {

             StompHeaderAccessor accessor =
                     MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);

             if (StompCommand.CONNECT.equals(accessor.getCommand())) {
                 Object raw = message
                         .getHeaders()
                         .get(SimpMessageHeaderAccessor.NATIVE_HEADERS);

                 if (raw instanceof Map) {
                     Object name = ((Map<?,?>) raw).get("email");

                     if (name instanceof LinkedList) {
                         String user = ((LinkedList<?>) name).get(0).toString();
                         accessor.setUser(new User(user));
                     }
                 }
             }
             return message;
         }
      });
   }
}

这是 JMS 侦听器,用于处理队列消息并将其发送给特定用户。

@Component
public class UserEventListener {

   private final Logger logger = LoggerFactory.getLogger(getClass());
   private final SimpMessagingTemplate template;

   @Autowired
   public UserEventListener(SimpMessagingTemplate pTemplate) {
      this.template = pTemplate;
   }

   @JmsListener(destination="user/events")
   public void onStatusChange(Map<String, Object> props) {

      if (props.containsKey("userEmail")) {
         logger.debug("Event for user received: {}", props.get("userEmail"));
         template.convertAndSendToUser((String)props.get("userEmail"), "/ccccc", props);
      }
   }
}

编辑 1:

经过更多调试后,WebSocket 的 "session" 似乎被 Spring 配置丢失了。我没有看到任何关于 "Disconnected" 消息或类似信息的日志信息,此外,如果我在发生这种情况时远程调试服务器,则在调试会话期间不会出现问题。一些想法?会话消失的 Spring 中的 class 是 DefaultSimpUserRegistry

经过更多研究,我发现了一个具有相同问题和解决方案的问题 。基本上结论是这样的:

通道拦截器不是验证用户的正确位置,我们需要使用自定义握手处理程序来更改它。