Channels改变Django在下面和经过Django的同步核心编织异步代码,容许Django项目不只处理HTTP,还须要处理须要长时间链接的协议 - WebSockets,MQTT,chatbots,amateur radio等等。python
它在保留Django同步和易用性的同时实现了这一点,容许您选择编写代码的方式 - 以Django视图,彻底异步或二者混合的方式同步。除此以外,它还提供了与Django的auth系统,会话系统等的集成,能够比以往更轻松地将仅HTTP项目扩展到其余协议。web
它还将此事件驱动架构与通道层捆绑在一块儿,该系统容许在流程之间轻松通讯,并将项目分红不一样的流程。redis
Channels提供了编写基本消费者的工具- 能够处理聊天消息或通知的各个部分 - 并将它们与URL路由,协议检测和其余便利的东西联系在一块儿,以制做完整的应用程序。docker
传统的Django视图仍然存在于Channels而且仍然可用,它们被封装在一个名为的ASGI应用程序中(ASGI是构建Channels的异步服务器规范的名称。与WSGI同样,它旨在不同的服务器和框架之间进行选择,而不是被锁定在Channels和服务器Daphne中。)django
1)为Channels建立根路由配置(在项目文件中建立routing.py)json
from channels.routing import ProtocolTypeRouter application = ProtocolTypeRouter({ # (http->django views is added by default) })
2)将Channels注册到settings.py INSTALLED_APPS中服务器
3)在根路由配置中指向Channels,settings.py中添加websocket
ASGI_APPLICATION = 'object.routing.application'
Channels服务器的运行架构
python manage.py runserver
#若是运行成功,显示
#Starting ASGI/Channels development server at http://127.0.0.1:8000/
当Django接受HTTP请求时,它会查询根URLconf以查找视图函数,而后调用视图函数来处理请求。相似地,当Channels接受WebSocket链接时,它会查询根路由配置以查找使用者,而后调用使用者的各类函数来处理来自链接的事件。app
1)app中建立文件routing.py,编写路由处理websocket请求
from django.conf.urls import url from . import consumers websocket_urlpatterns = [ url(r'^ws/chat/(?P<room_name>[^/]+)/$', consumers.ChatConsumer), ]
2)app中建立文件consumers.py,编写处理websocket脚本
from asgiref.sync import async_to_sync from channels.generic.websocket import WebsocketConsumer import json class ChatConsumer(WebsocketConsumer): def connect(self): self.room_name = self.scope['url_route']['kwargs']['room_name'] self.room_group_name = 'chat_%s' % self.room_name # Join room group async_to_sync(self.channel_layer.group_add)( self.room_group_name, self.channel_name ) self.accept() def disconnect(self, close_code): # Leave room group async_to_sync(self.channel_layer.group_discard)( self.room_group_name, self.channel_name ) # Receive message from WebSocket def receive(self, text_data): text_data_json = json.loads(text_data) message = text_data_json['message'] # Send message to room group async_to_sync(self.channel_layer.group_send)( self.room_group_name, { 'type': 'chat_message', 'message': message } ) # Receive message from room group def chat_message(self, event): message = event['message'] # Send message to WebSocket self.send(text_data=json.dumps({ 'message': message }))
3)将app路由注册到根路由中
from channels.auth import AuthMiddlewareStack from channels.routing import ProtocolTypeRouter, URLRouter import chat.routing application = ProtocolTypeRouter({ # (http->django views is added by default) 'websocket': AuthMiddlewareStack( URLRouter( chat.routing.websocket_urlpatterns ) ), })
channel layer是一种通讯系统。它容许多个消费者实例彼此交谈,以及与Django的其余部分交谈。
channel layer提供如下抽象:
使用一个使用Redis做为其后备存储的通道层。要在端口6379上启动Redis服务器
settings.py中添加
CHANNEL_LAYERS = { 'default': { 'BACKEND': 'channels_redis.core.RedisChannelLayer', 'CONFIG': { "hosts": [('127.0.0.1', 6379)], }, }, }
而后使用docker开启redis
docker run -p 6379:6379 -d redis:版本号
将消费者处理脚本重写为异步
from channels.generic.websocket import AsyncWebsocketConsumer import json class ChatConsumer(AsyncWebsocketConsumer): async def connect(self): self.room_name = self.scope['url_route']['kwargs']['room_name'] self.room_group_name = 'chat_%s' % self.room_name # Join room group await self.channel_layer.group_add( self.room_group_name, self.channel_name ) await self.accept() async def disconnect(self, close_code): # Leave room group await self.channel_layer.group_discard( self.room_group_name, self.channel_name ) # Receive message from WebSocket async def receive(self, text_data): text_data_json = json.loads(text_data) message = text_data_json['message'] # Send message to room group await self.channel_layer.group_send( self.room_group_name, { 'type': 'chat_message', 'message': message } ) # Receive message from room group async def chat_message(self, event): message = event['message'] # Send message to WebSocket await self.send(text_data=json.dumps({ 'message': message }))
异步使用者能够提供更高级别的性能,由于他们在处理请求时不须要建立其余线程。
这个新代码用于ChatConsumer与原始代码很是类似,但有如下区别:
ChatConsumer
如今继承AsyncWebsocketConsumer
而不是 WebsocketConsumer
。async def定义
await
用于调用执行I / O的异步函数。async_to_sync
在通道层上调用方法时再也不须要它。