【问题标题】:WebSocket messages are not delivered all the timesWebSocket 消息并非始终传递
【发布时间】:2019-12-28 16:01:54
【问题描述】:

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

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

这是 Spring 的配置类。

@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 的“会话”似乎因 Spring 配置而丢失。我没有看到任何关于“断开连接”消息或类似信息的日志信息,除非我在远程调试服务器时发生这种情况,在调试会话期间不会出现问题。有什么想法?会话消失的 Spring 类是 DefaultSimpUserRegistry。

【问题讨论】:

  • 调试更多内部显示一些奇怪的东西,userRegistry 与用户和会话之间的关系有时是空的但是我可以在接收事件之前在日志文件中看到 Processing SUBSCRIBE 和 Processing CONNECT 行。

标签: spring spring-boot websocket stomp sockjs


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2019-07-18
    • 2015-10-04
    • 1970-01-01
    • 2021-09-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多