Ama*_*dan 8 python django websocket python-asyncio django-channels
我有两个 websocket 服务器,分别称为 Main 和 Worker,这是所需的工作流程:
\n这可行吗?我在 Channels 中找不到任何 WS 客户端功能。我天真地尝试这样做(在consumers.py):
import websockets\n\nclass SampleConsumer(AsyncWebsocketConsumer):\n async def receive(self, text_data):\n async with websockets.connect(url) as worker_ws:\n await worker_ws.send(json.dumps({ 'to': 'Worker' }))\n result = json.loads(await worker_ws.recv())\n await self.send(text_data=json.dumps({ 'to': 'Client' })\nRun Code Online (Sandbox Code Playgroud)\n然而,似乎该with部分被阻止(Main 似乎不接受任何进一步的消息,直到收到 Worker 的响应)。我怀疑这是因为websockets运行了自己的循环,但我不确定。(编辑:我比较了一下id(asyncio.get_running_loop()),它似乎是相同的循环。我不知道为什么它会阻塞。)
响应{ "to": "Client" }不需要在这里,即使它是在不同的方法中,我也可以,只要它在收到 Worker 的响应时触发即可。
有没有办法做到这一点,还是我找错了树?
\n如果没有办法做到这一点,我正在考虑有一个线程(或进程?或单独的应用程序?)与 Worker 通信,并用于channel_layer与 Main 通信。这可行吗?如果我能得到确认(对于代码示例更是如此),我将不胜感激。
编辑我想我明白发生了什么(尽管仍在调查),但是 \xe2\x80\x94 我相信来自客户端的一个连接实例化了一个消费者,虽然不同的实例都可以同时运行,但在一个消费者实例中似乎在一个方法完成之前,该实例不允许启动第二个方法。它是否正确?现在看看将请求和等待响应代码移动到线程中是否可行。
\n每当我从另一个 WebSocket 服务器收到消息时,我都想在 Django 应用程序中处理消息。
我的想法是使用WebSockets客户端库,并使用Django 论坛上这篇manage.py文章中的命令将其作为单独的进程运行。
您可以定义一个异步协程client(websocket_url)来侦听从 WebSocket 服务器接收的消息。
import asyncio
import websockets
async def client(websocket_url):
async for websocket in websockets.connect(uri):
print("Connected to Websocket server")
try:
async for message in websocket:
# Process message received on the connection.
print(message)
except websockets.ConnectionClosed:
print("Connection lost! Retrying..")
continue #continue will retry websocket connection by exponential back off
Run Code Online (Sandbox Code Playgroud)
在上面的代码中connect()充当无限异步迭代器。更多内容请参见此处。
handle()您可以在自定义管理命令类的方法内运行上述协程。
runwsclient.py
from django.core.management.base import BaseCommand
class Command(BaseCommand):
def handle(self, *args, **options):
URL = "ws://example.com/messages"
print(f"Connecting to websocket server {URL}")
asyncio.run(client(URL))
Run Code Online (Sandbox Code Playgroud)
最后,运行manage.py命令。
python manage.py runwsclient
您还可以将处理消息传递给client(ws_url, msg_handler)它,以便处理逻辑将保留在客户端之外。
更新 31/05/2022:
我创建了一个 django 包,以最少的设置集成上述功能:django-websocketclient