当前位置: 首页 > 知识库问答 >
问题:

WebSocket消息并不总是传递

吕鸿朗
2023-03-14

我有一个带有WebSockets的应用程序,使用spring-boot应用程序作为后端,在客户端使用stomp/sockjs,spring-boot应用程序使用JMS队列消息并将更改通知给正确的用户。问题出在哪里?有时工作有时不工作,同样的代码和用户可以工作或不工作。

@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;
         }
      });
   }
}
@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

共有1个答案

柳涵意
2023-03-14

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

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

 类似资料:
  • 此应用程序收到 但是,当不存在web套接字会话,并且JMSProducer将消息发送到QueueSenderSessionBean中的目标“jms/notificationQueue”时,消息会立即在NotificationEndpoint中使用。这不是我的意图。 我的目的是让队列保留消息,直到用户连接到NotificationEndpoint。如果用户没有连接到NotificationEndpo

  • 在我的聊天应用程序中,每当用户收到新消息时,我使用FCM和Firebase功能发送通知。 为此,我有一个FirebaseMessagingService,它覆盖了。除此之外,此服务还覆盖。每当用户第一次启动应用程序时,就会调用,我检索一个新令牌并将其存储在Firebase实时数据库中。 然后我去和一些用户聊天(不关闭应用程序)。当我收到新消息时,我会收到通知。调用。 问题是,当我关闭应用程序,然后

  • 一个人气正在上升的确保安全并发的方式是 消息传递(message passing),这里线程或 actor 通过发送包含数据的消息来相互沟通。这个思想来源于 Go 编程语言文档中的口号: Do not communicate by sharing memory; instead, share memory by communicating. 不要共享内存来通讯;而是要通讯来共享内存。 —Effec

  • 所以我使用传单-反应,我需要添加一些圆圈标记。 现在这个代码起作用了...有时。在地图上单击一个圆圈标记应该添加,但有时它不是。似乎是随机的,它只是不会添加一个可见的标记。有时标记会变得可见,如果我改变缩放级别,但不总是。所有的代码每次都运行,所以并不是没有调用addMarker(),而且总是运行删除最后一个标记(通过清除标记层)。 谢了,艾德。

  • 由于内容脚本在网页而不是扩展程序的上下文中运行,因此它们通常需要某种与扩展程序其余部分进行通信的方式。例如,RSS 阅读器扩展程序可以使用内容脚本来检测页面上 RSS 摘要的存在,然后通知后台页面以显示该页面的操作图标。 扩展及其内容脚本之间的通信使用消息传递来实现。任何一方都可以监听从另一端发送的消息,并在同一通道上进行响应。消息可以包含任何有效的 JSON 对象(空,布尔值,数字,字符串,数组

  • ms tcp nodelay 描述: 在信差的 TCP 会话上禁用 nagle 算法。 类型: Boolean 是否必需: No 默认值: true ms initial backoff 描述: 出错时重连的初始等待时间。 类型: Double 是否必需: No 默认值: .2 ms max backoff 描述: 出错重连时等待的最大时间。 类型: Double 是否必需: No 默认值: 15