繁体   English   中英

Python WebSocket卡住了

[英]Python websockets get stuck

我有一个可通过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)

显然,在真实代码中,我不会随机睡眠,也不会使用给定的消息列表,但这勾勒了我处理WebSocket的方式。 在实际环境中,也可能会发生一些通过websocket发送的错误,因此理论上可能会发生并行send(),但我从未遇到过这种情况。

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

我的问题是:

  • 这种使用websocket的方法有根本的错误吗?
  • 并发调用send()方法是否有危险?
  • 您能建议一些有关使用Websocket和asyncio的好的做法吗?

谢谢你

recv函数仅在接收到消息时才返回,并且似乎有2个连接正在等待彼此的消息,因此当它们等待彼此的消息并且无法发送任何内容时,可能会出现类似于“死锁”的情况。 也许您应该尝试重新考虑整体算法,以使其更安全。

并且,当然,尝试添加更多的调试输出,看看实际发生了什么。

send()方法的并发调用有危险吗?

如果并发意味着在同一线程中但在独立调度的协程中,则并行发送就可以了。 但是要注意同一连接上的“并行” recv ,因为协程调度的顺序可能远非显而易见,而是决定对recv调用将首先获得消息的原因。

您能建议一些有关使用Websocket和asyncio的好的做法吗?

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM