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

Python Socket.IO/AIOHTTP服务器async/await机制问题排查

为什么Python-Socket.IO的async处理函数加sleep后只收到第一条消息?

首先澄清你的误区:async函数并不是只能同时运行一个实例,问题出在两个关键地方——你的客户端进程过早退出,以及Python-Socket.IO默认对单个客户端的事件采用串行处理的机制。

1. 客户端进程过早退出是直接原因

看你的Node.js客户端代码,在连续调用三次emit后,进程没有任何后续异步任务,会立刻退出,导致Socket连接被强制断开。这时候服务器可能只接收到第一条消息,或者后两条消息还没来得及发送/处理,连接就已经断了。

你可以修改客户端代码,让它保持连接一段时间,确保服务器有足够时间处理所有消息:

const io = require('socket.io-client');
const socket = io('ws://localhost:8080');

// 等连接建立后再发送消息更可靠
socket.on('connect', () => {
  socket.emit('sendText', 'hey 1');
  socket.emit('sendText', 'hey 2');
  socket.emit('sendText', 'hey 3');
});

// 保持进程运行,避免过早退出
setTimeout(() => {
  socket.disconnect();
  process.exit();
}, 5000); // 等待5秒确保所有消息处理完成

2. Python-Socket.IO的单客户端事件串行处理机制

即使客户端保持连接,你也会发现三条消息的处理是按顺序来的——第一条处理完(sleep结束),才会开始处理第二条。这是因为Python-Socket.IO默认对同一个客户端(同一个sid)的所有事件采用串行处理:每个客户端有一个独立的事件队列,前一个事件的处理函数执行完成前,后面的事件会被排队等待,不会触发处理。

如果你希望同一个客户端的事件可以并发处理,不要在事件处理函数里直接执行耗时的await操作,而是用sio.start_background_task把耗时逻辑放到后台任务中,让事件处理函数立刻返回,这样后续事件可以被及时处理:

import asyncio
from aiohttp import web
import socketio
import random

sio = socketio.AsyncServer(async_mode='aiohttp')
app = web.Application()
sio.attach(app)

@sio.on('connect')
def connect(sid, environ):
    print("connected: ", sid)

@sio.on('sendText')
async def message(sid, data):
    print("message ", data)
    # 启动后台任务处理耗时操作,当前函数立刻返回
    await sio.start_background_task(handle_delayed_log, data)

async def handle_delayed_log(data):
    await asyncio.sleep(1 * random.random())
    print('waited', data)

@sio.on('disconnect')
def disconnect(sid):
    print('disconnect ', sid)

if __name__ == '__main__':
    web.run_app(app, host='0.0.0.0', port=8080)

这样修改后,三条消息的print("message ", data)会立刻依次输出,而waited的输出则会随机延迟,互不阻塞。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:58:18