![](/img/trans.png)
[英]Django channels would not start redis server using CHANNEL_LAYERS
[英]Django Channels 2.0 channel_layers not communicating
所以我一直在遷移使用Django Channels 1.x-> 2.x +的服務器
原始設計將使用getAFTreeTask.delay(message.reply_channel.name)
將任務發送到celery,並且通過訪問channel_name
可以愉快地異步答復
from celery import task
from channels import Channel
@task
def getAFTreeTask(channel_name):
tree = Request().cache_af_tree()
Channel(channel_name).send({
"text": json.dumps({
"channel": "AF_INIT",
"payload": tree
})
})
現在,由於各種原因,我已將服務器遷移到Channels 2.x +。 根據文檔
class Consumer(JsonWebsocketConsumer):
def connect(self):
print("Client Connected: ", self.channel_name)
self.accept()
def receive_json(self, content, **kwargs):
print(content)
parse_request(self.channel_name, content)
def disconnect(self, content):
print(content)
def chat_message(self, event):
print("Entered reply channel")
print(event)
如果我使用正確的channel_name,則這樣設置的使用者應通過通道層接收請求,現在,如果響應可以訪問self.send_json()
或self.send()
,則該使用者可以正確地用作發送-接收websocket。其他通用使用者,所以我假設我的所有設置都是正確的,我的問題是當我嘗試使用通道層發送某些內容時(根據https://channels.readthedocs.io/en/latest/topics /channel_layers.html#single-channels )
from channels.layers import get_channel_layer
from asgiref.sync import AsyncToSync
def parse_request(channel_name, content):
print("parsed ", channel_name, content)
channel_layer = get_channel_layer()
AsyncToSync(channel_layer.send)(channel_name, {
"type": "chat.message",
"text": "Hello there!",
})
我懂了
編輯(完整堆棧跟蹤 ):
2018-02-02 18:28:35,984 ERROR Exception inside application: There is no current event loop in thread 'Thread-3'.
File "/usr/lib/python3.5/asyncio/tasks.py", line 241, in _step
result = coro.throw(exc)
File "/home/chris/Env/myapp/lib/python3.5/site-packages/channels/consumer.py", line 51, in __call__
await await_many_dispatch([receive, self.channel_receive], self.dispatch)
File "/home/chris/Env/myapp/lib/python3.5/site-packages/channels/utils.py", line 48, in await_many_dispatch
await dispatch(result)
File "/home/chris/Env/myapp/lib/python3.5/site-packages/asgiref/sync.py", line 81, in inner
return await async_func(*args, **kwargs)
File "/home/chris/Env/myapp/lib/python3.5/site-packages/asgiref/sync.py", line 65, in __call__
return await asyncio.wait_for(future, timeout=None)
File "/usr/lib/python3.5/asyncio/tasks.py", line 373, in wait_for
return (yield from fut)
File "/usr/lib/python3.5/asyncio/futures.py", line 361, in __iter__
yield self # This tells Task to wait for completion.
File "/usr/lib/python3.5/asyncio/tasks.py", line 296, in _wakeup
future.result()
File "/usr/lib/python3.5/asyncio/futures.py", line 274, in result
raise self._exception
File "/usr/lib/python3.5/concurrent/futures/thread.py", line 55, in run
result = self.fn(*self.args, **self.kwargs)
File "/home/chris/Env/myapp/lib/python3.5/site-packages/asgiref/sync.py", line 74, in thread_handler
raise e
File "/home/chris/Env/myapp/lib/python3.5/site-packages/asgiref/sync.py", line 72, in thread_handler
self.func(*args, **kwargs)
File "/home/chris/Env/myapp/lib/python3.5/site-packages/channels/consumer.py", line 93, in dispatch
handler(message)
File "/home/chris/Env/myapp/lib/python3.5/site-packages/channels/generic/websocket.py", line 40, in websocket_receive
self.receive(text_data=message["text"])
File "/home/chris/Env/myapp/lib/python3.5/site-packages/channels/generic/websocket.py", line 104, in receive
self.receive_json(self.decode_json(text_data), **kwargs)
File "./MYAPP/API/consumers.py", line 13, in receive_json
parse_api_request(self.channel_name, content)
File "./MYAPP/API/api_request.py", line 16, in parse_api_request
AsyncToSync(channel_layer.send)(channel_name, {
File "/home/chris/Env/myapp/lib/python3.5/site-packages/asgiref/sync.py", line 17, in __init__
self.main_event_loop = asyncio.get_event_loop()
File "/usr/lib/python3.5/asyncio/events.py", line 632, in get_event_loop
return get_event_loop_policy().get_event_loop()
File "/usr/lib/python3.5/asyncio/events.py", line 578, in get_event_loop
% threading.current_thread().name)
There is no current event loop in thread 'Thread-3'.
如果我不使用AsyncToSync
我得到(根據文檔,我不應該這樣做, 只是為了檢查 )
2018-02-02 18:34:27,965 WARNING ./MYAPP/API/api_request.py:18: builtins.RuntimeWarning: coroutine 'RedisChannelLayer.send' was never awaited
當我完全按照指南進行操作時我不明白,我也嘗試從celery任務(一個單獨的線程)中進行答復,但沒有收到相同的錯誤,但是什么也沒發生,celery日志只是說任務已完成,但是我沒有得到回復。
另外,嘗試直接通過
AsyncToSync(channel_layer.send)(channel_name, {
"type": "websocket.send",
"text": "Hello there!",
})
從線程內外獲得相同的非結果。
是否有人能夠通過Consumers
對象外部的channel_layers發送。
僅供參考我的settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels',
'myapp',
]
ASGI_APPLICATION = "myapp.routing.application"
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [("localhost", 6379)],
},
},
}
經過安德烈斯·戈德溫的回復 :
我發現這是asgiref
<2.1.3中的錯誤,通過升級SyncToAsync / AsyncToSync的返回值已得到修復!
因此,對於任何有興趣的人,我的工作實現都是:
consumers.py
from channels.consumer import AsyncConsumer
class My_Consumer(AsyncConsumer):
async def websocket_connect(self, event):
print("Connected")
print(event)
print(self.channel_name)
await self.send({
"type": "websocket.accept",
})
async def websocket_receive(self, event):
print("Received")
print(event)
parse_api_request(self.channel_name, json.loads(event['text']))
async def celery_message(self, event):
print("Service Received")
print(event)
await self.send({
"type": "websocket.send",
"text": event["text"],
})
task.py
from channels.layers import get_channel_layer
from asgiref.sync import AsyncToSync
def async_send(channel_name, text):
channel_layer = get_channel_layer()
AsyncToSync(channel_layer.send)(
channel_name,
{"type": "celery.message",
"text": json.dumps(text)
})
def getAFTree(channel_name, message):
getAFTreeTask.delay(channel_name, message)
@task
def getAFTreeTask(channel_name, message):
tree = Request().cache_af_tree()
async_send(channel_name, {
"channel": "AF_INIT",
"payload": tree
})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.