You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何基于RabbitMQ的STOMP比普通WebSocket传输速度更快?

问题:RabbitMQ+STOMP比纯WebSocket发送消息更快的原因分析

当用Python服务器向JavaScript客户端发送10万条300字符的消息时,RabbitMQ+STOMP方案耗时10-20秒,反而比纯WebSocket方案的至少22秒更快。原本以为STOMP是WebSocket叠加RabbitMQ的额外处理,理论上应该更慢,特此咨询该现象的原因,是否与asyncio有关?


一、RabbitMQ+STOMP方案代码

Python服务端

import stomp

PORT = 61613
LOCALHOST = '0.0.0.0'
conn = stomp.Connection11([(LOCALHOST, PORT)])  
# conn.start()
conn.connect('guest','guest')
from random import choice
from string import ascii_uppercase
from time import time
conn.send(body="start",destination='/queue/test')
t = time()
for i in range(100000):
    conn.send(body=''.join(choice(ascii_uppercase) for i in range(300)),destination='/queue/test')
t = time() - t
conn.send(body="end",destination='/queue/test')
print()
print(100000, "took ", t*1000, " ms")

conn.disconnect()

JavaScript客户端

<script>
    var client = Stomp.client('ws://localhost:15674/ws');
    var test = document.getElementById("test")
    client.debug = null;
    var date1 = null
    var date2 = null
    test.innerText = "READY... START!"

    var sub = function(d) {
        test.innerText = d.body
        if(d.body == "start") {
            date1 = new Date().valueOf()
        }
        
        if(d.body == "end") {
            date2 = new Date().valueOf()
            console.log(100000, "took ", date2 - date1, " ms")
        }
    }
    var on_connect = function(x) {
        id = client.subscribe("/queue/test", sub);
        console.log("connected")
    };
    var on_error =  function(e) {
      console.log('error', e);
    };
    
    client.connect('guest', 'guest', on_connect, on_error, '/');
</script>

二、纯WebSocket方案代码

Python服务端

import asyncio
import websockets
import random
import string
async def echo(websocket):
    print("connected")
    await websocket.send("start")

    for i in range(100000):
        await websocket.send(''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(300)))

    await websocket.send("end")
    print("sent")

async def main():
    async with websockets.serve(echo, "localhost", 8765):
        await asyncio.Future() 

JavaScript客户端

<body>
    <div id="test">
        READY... SET... GO!!
    </div>
    <script>
        var time1 = null
        var time2 = null

        var socket = new WebSocket('ws://localhost:8765/ws');
        socket.onmessage = function(e) {
            var server_message = e.data;
            if (server_message == "start") {
                time1 = new Date().valueOf()
            }
            if (server_message == "end") {
                time2 = new Date().valueOf()
                console.log("100000 messages took ", (time2 - time1) / 1000, "seconds")
            }
            document.getElementById("test").innerText = server_message
        }
    </script>
</body>

原因分析

  1. asyncio的调度开销:纯WebSocket方案中,Python服务端在循环里逐个调用await websocket.send(),每次await都会让出事件循环,等待发送回调完成,频繁的上下文切换会带来额外开销。而stomp库的conn.send()是同步阻塞发送,底层IO处理更高效,没有频繁的事件循环切换。
  2. RabbitMQ的批量转发优化:RabbitMQ作为消息中间件,会对消息进行缓存批量转发,减少了TCP层面的小包传输和握手开销,提升了整体吞吐量;纯WebSocket则是逐个发送消息,没有批量处理机制。
  3. 协议层面的效率差异:STOMP协议的帧结构虽然有额外头部,但RabbitMQ会对帧进行合并或高效序列化处理;纯WebSocket的send()每次都是单独的消息帧,协议 overhead更高。
  4. 客户端处理差异:纯WebSocket客户端每条消息都会触发onmessage并更新DOM,频繁的DOM操作会占用客户端资源,拖慢耗时统计;STOMP客户端可能对消息接收做了批量回调优化,减少了这类开销。

内容的提问来源于stack exchange,提问作者qwerty_99

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 09:35:22