Python WebSocket被卡住了

Python WebSocket被卡住了,python,websocket,python-asyncio,Python,Websocket,Python Asyncio,我有一个通过websocket端点提供的python服务器。 在服务连接期间,它还与一些后端服务进行通信。此通信是异步的,可能会触发websocket的send()方法 当为单个客户提供服务时,它似乎工作正常。然而,当多个客户端并行服务时,处理连接的一些例程偶尔会卡住。更准确地说,它似乎阻塞了recv()方法 实际代码有点复杂,问题比我描述的稍微复杂一些,不过,我提供了一个简单的代码框架,概述了我使用WebSocket的方式: class MinimalConversation(object):

我有一个通过websocket端点提供的python服务器。 在服务连接期间,它还与一些后端服务进行通信。此通信是异步的,可能会触发websocket的send()方法

当为单个客户提供服务时,它似乎工作正常。然而,当多个客户端并行服务时,处理连接的一些例程偶尔会卡住。更准确地说,它似乎阻塞了recv()方法

实际代码有点复杂,问题比我描述的稍微复杂一些,不过,我提供了一个简单的代码框架,概述了我使用WebSocket的方式:

class MinimalConversation(object):

    def __init__(self, ws, worker_sck, messages, should_continue_conversation, should_continue_listen):
        self.ws = ws
        self.messages = messages
        self.worker_sck = worker_sck
        self.should_continue_conversation = should_continue_conversation
        self.should_continue_listen = should_continue_listen

async def run_conversation(self):
        serving_future = asyncio.ensure_future(self.serve_connection())
        listening_future = asyncio.ensure_future(self.handle_worker())
        await asyncio.wait([serving_future, listening_future], return_when=asyncio.ALL_COMPLETED)

async def serve_connection(self):
        while self.should_continue_conversation():
            await self.ws.recv()
            logger.debug("Message received")
            self.sleep_randomly(10, 5)
            await self.worker_sck.send(b"Dummy")

async def handle_worker(self):
        while self.should_continue_listen():
            self.sleep_randomly(50, 40)
            await self.worker_sck.recv()
            await self.ws.send(self.messages.pop())

def sleep_randomly(self, mean, dev):
        delta = random.randint(1, dev) / 1000
        if random.random() < .5:
            delta *= -1
        time.sleep(mean / 1000 + delta)
类会话(对象):
定义初始化(self、ws、worker、sck、消息、是否继续对话、是否继续侦听):
self.ws=ws
self.messages=消息
self.worker\u sck=worker\u sck
self.should\u continue\u conversation=should\u continue\u conversation
self.should\u continue\u listen=should\u continue\u listen
异步def运行会话(自):
serving\u future=asyncio.Survey\u future(self.serve\u connection())
侦听\u future=asyncio.sure\u future(self.handle\u worker())
wait asyncio.wait([service\u future,listening\u future],返回\u when=asyncio.ALL\u COMPLETED)
异步def SERVER_连接(自):
而self.是否应继续对话():
wait self.ws.recv()
logger.debug(“收到消息”)
随机自睡眠(10,5)
等待自我工作人员发送(b“虚拟”)
异步def句柄\u工作程序(自身):
而self.是否应继续听()
随机自睡眠(50,40)
等待self.worker_sck.recv()
等待self.ws.send(self.messages.pop())
def sleep_随机(自我、平均值、开发):
delta=random.randint(1,dev)/1000
如果random.random()<.5:
delta*=-1
睡眠时间(平均值/1000+增量)
显然,在真正的代码中,我不会随机睡眠,也不会使用给定的消息列表,但这只是我处理WebSocket的方式。在实际设置中,也可能会发生通过websocket发送的一些错误,因此理论上可能会发生parallel sends(),但我从未遇到过这种情况

代码从处理程序函数运行,该函数作为参数传递给websockets.service(),初始化MinimalConversation对象并调用run_conversation()方法

我的问题是:

  • 这种WebSocket的使用有什么根本性的问题吗
  • send()方法的并发调用是否危险
  • 您能否就WebSocket和asyncio的使用提出一些好的建议

Thak you.

recv
函数仅在收到消息时返回,并且似乎有两个连接在等待对方的消息,因此当它们等待对方的消息并且无法发送任何内容时,可能会出现类似于“死锁”的情况。也许你应该重新考虑一下整个算法,这样会更安全

当然,尝试添加更多调试输出,看看真正发生了什么

send()方法的并发调用是否危险

如果并发是指在同一个线程中,但在独立调度的协程中,那么并行发送就可以了。但是在同一个连接上使用“parallel”
recv
时要小心,因为协程调度的顺序可能并不明显,它决定了对
recv
的哪个调用将首先获得消息

您能否就WebSocket和asyncio的使用提出一些好的建议

根据我的经验,最简单的方法是为传入连接创建一个专用任务,该任务将在连接上重复调用
recv
,直到连接关闭。您可以将连接存储在某个位置,并在
finally
块中删除它,然后可以从其他协同路由中使用它发送内容