【发布时间】:2024-04-15 03:10:01
【问题描述】:
我已经为一个性能问题苦苦挣扎了两个多月,但我无法解决它。因此,我想请教一下问题可能是什么。
问题
我们使用 Spring Websocket 开发一个应用程序,其中客户端订阅其用户队列 (/user/exchange/amq.direct/update) 以接收有关它们的更新。我设置了一个 JMeter 测试,它订阅用户队列并每 4 秒发送一条消息,会话长度为 12 分钟。当有大约 300 个线程在运行时(以大约 4500 个请求/分钟结束),服务器的响应时间急剧增加到 6 秒以上(我认为在我的 JMeter 测试中超时)。
测试在单独的机器上运行,应用程序在 Linux (Debian) 机器上运行,没有其他正在运行的应用程序。
我已经尝试过的
- 将外部消息代理 (rabbitMQ) 与内部消息代理交换。有趣的是,使用内部代理我可以处理多达 2000 个线程,但我会进入相同的超时。
- 我删除了所有业务逻辑,只发送一个简单的字符串作为 STOMP 消息
- 我为
ClientInboundChannel和ClientOutboundChannel尝试了不同的配置 - 我在
WebSocketMessageBrokerConfigurer中尝试了不同的SendBufferSizeLimit - 为了验证我没有网络问题,我确实测量了来自
ClientInboundChannel的传入消息的时间,直到它通过为它们实现ChannelInterceptors在ClientOutboundChannel中发送出去。这证实了答案确实需要超过 6 秒才能发出。 - 在 websocket 的响应时间变得如此糟糕的时候(顺便说一句,这已经影响了新线程的 STOMP 连接调用)我对传统的 http 请求没有任何问题。
- 我的飞行记录显示 CPU 没有问题,峰值仅为 40%,RAM 也远低于 1.5 GB 左右的阈值。
- 我也看不到线程争用或热方法。
- 我没有用完文件描述符。
- 垃圾收集没问题。我在 7 分钟内只运行了 4 次,GC 时间在 200-300 毫秒左右
由于我已经在这个话题上工作了很长一段时间,我可能忘记了很多我也尝试过的东西,所以请不要犹豫,开始对话。
我希望你能给我更多的灵感去哪里寻找问题。
更新:
我发现我可以增加 SimpleMessageBroker 使用的 DefaultSubscriptionRegistry 的缓存限制。这导致使用该应用程序只需处理数千名用户。所以看起来这是 RabbitMQ 的问题。我确实使用PerfTest 工具测试了我们的 RabbitMQ,并且通过该测试我没有遇到任何问题。而且测试的不是使用STOMP插件,而是amqp。
那么 Spring Websocket 中的外部消息代理有类似的限制吗?
更新 2:
我能够使用示例应用程序重现该问题,您可以在 github 上找到该示例应用程序: https://github.com/mld-ger/spring-websocket-performance-issue
由于我认为这可能是 Spring 中的错误,我开了一张票:https://jira.spring.io/browse/SPR-16950
【问题讨论】:
标签: java spring performance rabbitmq spring-websocket