Stomp 未接收 CONNECTED 框架(角度 + 弹簧)

问题描述 投票:0回答:2

我目前正在我的 Spring Boot 2 + Angular 14 应用程序上使用 SockJS 和 Stomp 实现后端到前端消息机制

我得到一个随机行为,有时一切正常,但有时 websocket 没有收到任何消息。

当它不起作用时,WS消息看起来像这样

但是当它起作用时

主要区别在于,当它工作时,它会收到一个 CONNECTED 帧并触发订阅。我不明白为什么有时它没有收到 CONNECTED 帧。

我的后端配置

@Configuration
@EnableWebSocketMessageBroker
class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry
            .addEndpoint("/socket/no")
            .setAllowedOriginPatterns("*").withSockJS();
    }
}

前端客户端(app.component.ts > ngOnInit)

    const socketUrl = `${window.origin}/socket/no`;
    const stompClient = new Client({
      brokerURL: socketUrl,
      connectHeaders: {},
      debug: function (str) {
        console.debug(str);
      },
      reconnectDelay: 5000,
      webSocketFactory: function () {
        return new SockJS(socketUrl);
      },
      onConnect: function () {
        stompClient.subscribe("/topic/no", function (msg) {
          console.log("message received");
        });
      },
    });

    stompClient.activate();
  

proxy.conf.json

"/socket/**": {
        "target": "http://localhost:8080",
        "secure": false,
        "ws": true
    },

我觉得当我在小页面上打开角度应用程序时它更有可能工作。 例如,我的主页有很多组件,需要一些时间才能加载。但是,当我使用简单网格视图的 url 打开应用程序时,它有更多的机会工作,但并非总是如此。

基于这种感觉,我认为这是一个前端问题。也许是 websocket 所需的角度组件而不是加载器或类似的东西。

在后端,我在发送连接帧后看到此日志

ms.w.s.h.LoggingWebSocketHandlerDecorator New WebSocketServerSockJsSession[id=naeygmcp]
angular websocket stomp spring-websocket
2个回答
1
投票

您的 WebSocket 线程池可能已耗尽。默认情况下,线程池配置为:

core pool size = CORE * 2
max pool size  = CORE * 2
queue capacity = Integer.MAX_VALUE

成功连接的 STOMP 客户端会经历以下阶段:

  1. 建立 WebSocket 连接(HTTP 状态:101)
  2. 发送 STOMP 命令
    CONNECT
  3. 收到 STOMP 命令
    CONNECTED
  4. 发送 STOMP 命令
    SUBSCRIBE
  5. 发送 STOMP 命令
    SEND

第一个只是一个 HTTP 请求,因此它不会使用该线程池。相反,STOMP 协议下的其余阶段都将使用该池。也许您的应用程序中有一些长时间运行的请求占用了池,导致客户端卡在第二阶段。

一个可能的解决方案是调整该池:

@Configuration
@EnableWebSocketMessageBroker
public class DefaultWebSocketMessageBrokerConfigurer implements WebSocketMessageBrokerConfigurer {
    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration
                .taskExecutor()
                .corePoolSize(8)
                .maxPoolSize(512)
                .queueCapacity(32)
                .keepAliveSeconds(30);
    }
}

0
投票

最后,从 Spring Boot 2.4 迁移到 2.7 解决了这个问题。 现在我的应用程序已经迁移到 Spring Boot 3.0 一个月了,问题没有再出现

看起来与此相关https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-22971

© www.soinside.com 2019 - 2024. All rights reserved.