网站部署在华为云服务器上,Debian系统,使用Django+Nginx+uwsgi搭建。最终效果如下图所示。
一、响应逻辑顺序
1. 聊天页面请求
客户端请求/chat/(输入聊天室房间号界面)和/chat/room_name(某个聊天室页面)链接时,由Nginx转到Django由urls.py解析并返回相应页面,在返回的聊天室页面内置了javascript程序,请求建立wss:/ws/chat/room_name的websocket连接。
2. websocket连接请求
客户端向Nginx发送websocket连接请求,根据Ngnix配置文件location /ws {}中设置的反向代理,请求被转到本地的7001端口( http://127.0.0.1:7001),将由运行在该端口上的由daphne托管的asgi服务解析并响应(配置文件为myproject/asgi.py)。
3. asgi.py解析并响应
asgi.py中定义的application定义了websocket的解析规则,具体由/myproject/routing.py中的websocket_urlpatterns进行地址解析,通过Channels由myapp/comsumers.py进行异步信息处理并响应。
二、配置Channels和asgi
1. 安装Channels
sudo pip3 install channels
2. settings.py中添加应用并配置channels和asgi
INSTALLED_APPS = [
'django.contrib.auth',
'django.contrib.admin',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels',
'myapp',
]
ASGI_APPLICATION = 'myproject.asgi.application'
# Channels_Layers相关配置
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('127.0.0.1', 6379)],
},
},
}
# 配置认证后端
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
)
Django Channels利用 Redis 作为通道层来管理客户端和服务器之间的通信。当客户端通过 WebSocket 连接发送消息时,Django Channels 会使用 Redis 将消息分发到所有连接的客户端。Redis 充当消息代理,实时有效地处理消息的路由和传递。
ASGI_APPLICATION指向Django项目下的asgi.py文件中的application。
3. 配置asgi.py文件
import os
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
django.setup()
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from myproject import routings
application = ProtocolTypeRouter({
'http':get_asgi_application(), #支持http请求
'websocket':AuthMiddlewareStack(
URLRouter(routings.websocket_urlpatterns) #支持webscoket请求
),
})
此处django.setup()和DJANGO_SETTINGS_MODULE设置应放在导入模块前,否则容易出现如下报错:
django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
Requested setting DEBUG, but settings are not configured.
You must either define the environment variable DJANGO_SETTINGS_MODULE
or call settings.configure() before accessing settings...
WSGI和ASGI 的主要区别是同步VS异步,WSGI是同步的,每个请求必须等待前一个请求完成。而ASGI是异步的,可以同时处理多个请求。 WSGI主要用于HTTP协议,ASGI旨在支持WebSocket、HTTP2等协议。ASGI的主要特点是异步非阻塞,它能够更好地处理并发请求。
上述设置中websocket地址解析由Django项目下的routings.py完成,其功能与urls.py类似。
4. 配置routings.py
from django.urls import path
from myapp import consumers
websocket_urlpatterns = [
path(r'ws/chat/<str:room_name>/', consumers.ChatConsumer.as_asgi())
]
myapp为新建的应用,其下的consumers.py文件定义了websocket的响应函数ChatConsumer。
5. 配置myapp/consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer
from asgir