了解 python 套接字 io / aiohttp 服务器中的异步等待
Understanding async await in python socket io / aiohttp server
我正在尝试使用 python-socketio 设置 socket.io 服务器。
这是一个最小的工作示例:
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 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)
这个运行很好,我可以执行(这里是node.js)例如
const io = require('socket.io-client');
const socket = io('ws://localhost:8080');
socket.emit('sendText', 'hey 1')
socket.emit('sendText', 'hey 2')
socket.emit('sendText', 'hey 3')
如果我 运行 服务器和 运行 上面的节点脚本我得到服务器端
connected: c1e687f0e2724b339fcdbefdb5aaa8f8
message hey 1
message hey 2
message hey 3
但是,如果我取消注释代码中带有 await sleep 的行,我只会收到第一条消息:
connected: 816fb6700f5143f7875b20a252c65f33
message hey 1
waited hey 1
我不明白为什么没有显示下一条消息。
async def message
运行 只能同时出现一个吗?或者为什么?
我确定我不了解有关其工作原理的一些非常基本的东西。如果有人能指出我不理解的地方,我将不胜感激。
我是 python-socketio 包的作者。我认为这里有两个问题。我可以回答你的问题:
Can only one instance of async def message run at the same time? Or why?
我的 Socket.IO 服务器序列化从给定客户端接收的事件。因此,例如,如果客户端 A 发送一个运行一分钟的事件,则 A 在该分钟内发送的任何其他事件都将排队,等待第一个事件先完成。如果客户端 B 在那一分钟内发送了一个事件,它将被立即处理。来自客户端的事件被人为序列化的原因是为了防止由于同一客户端 运行 的两个或多个处理程序并行而发生竞争条件或其他副作用。可以使用 async_handlers
选项关闭此事件序列化:
sio = socketio.AsyncServer(async_mode='aiohttp', async_handlers=True)
使用 aiohttp 2.3.7 和 async_handlers=True
您的三个事件几乎同时收到,然后所有处理程序在它们的睡眠期间并行等待。
不幸的是,这并不能解释第二个和第三个事件从未到达服务器。我已经验证这些事件在 aiohttp 2.2.5 中已正确排队并按顺序执行,但这与 2.3.0 一直中断到 2.3.7。我目前的理论是,2.3.0 中引入的一项更改导致这些在任务休眠时到达的消息被丢弃,但尚未找到发生这种情况的原因。
我正在尝试使用 python-socketio 设置 socket.io 服务器。 这是一个最小的工作示例:
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 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)
这个运行很好,我可以执行(这里是node.js)例如
const io = require('socket.io-client');
const socket = io('ws://localhost:8080');
socket.emit('sendText', 'hey 1')
socket.emit('sendText', 'hey 2')
socket.emit('sendText', 'hey 3')
如果我 运行 服务器和 运行 上面的节点脚本我得到服务器端
connected: c1e687f0e2724b339fcdbefdb5aaa8f8
message hey 1
message hey 2
message hey 3
但是,如果我取消注释代码中带有 await sleep 的行,我只会收到第一条消息:
connected: 816fb6700f5143f7875b20a252c65f33
message hey 1
waited hey 1
我不明白为什么没有显示下一条消息。
async def message
运行 只能同时出现一个吗?或者为什么?
我确定我不了解有关其工作原理的一些非常基本的东西。如果有人能指出我不理解的地方,我将不胜感激。
我是 python-socketio 包的作者。我认为这里有两个问题。我可以回答你的问题:
Can only one instance of async def message run at the same time? Or why?
我的 Socket.IO 服务器序列化从给定客户端接收的事件。因此,例如,如果客户端 A 发送一个运行一分钟的事件,则 A 在该分钟内发送的任何其他事件都将排队,等待第一个事件先完成。如果客户端 B 在那一分钟内发送了一个事件,它将被立即处理。来自客户端的事件被人为序列化的原因是为了防止由于同一客户端 运行 的两个或多个处理程序并行而发生竞争条件或其他副作用。可以使用 async_handlers
选项关闭此事件序列化:
sio = socketio.AsyncServer(async_mode='aiohttp', async_handlers=True)
使用 aiohttp 2.3.7 和 async_handlers=True
您的三个事件几乎同时收到,然后所有处理程序在它们的睡眠期间并行等待。
不幸的是,这并不能解释第二个和第三个事件从未到达服务器。我已经验证这些事件在 aiohttp 2.2.5 中已正确排队并按顺序执行,但这与 2.3.0 一直中断到 2.3.7。我目前的理论是,2.3.0 中引入的一项更改导致这些在任务休眠时到达的消息被丢弃,但尚未找到发生这种情况的原因。