Daphne 是 Django Channels 项目的一部分,专门用于为 Django 提供支持 HTTP、WebSocket、HTTP2 和 ASGI 协议的异步服务器。Daphne 是一个开源的 Python 异步服务器,它可以帮助开发者运行异步应用程序,并且非常适合与 Django Channels 一起使用,为 Django 项目增加实时通信的能力。
通过使用 Daphne,Django 开发者可以将传统的同步 HTTP 请求扩展为支持 WebSocket 和异步任务处理的高性能应用,从而更好地支持现代 Web 应用的实时功能。
⭕️宇宙起点
- 🔨 Daphne 的主要特点
- 1. 支持 ASGI 协议
- 2. 与 Django Channels 集成
- 3. 多协议支持
- 4. 高性能异步处理
- 📦 Daphne 的安装与使用
- 1. 安装 Daphne
- 2. 配置 ASGI 文件
- 3. 配置 WebSocket 路由
- 4. 创建 WebSocket Consumer
- 5. 运行 Daphne 服务器
- 🧱 应用场景
- ♨️ 使用 Daphne 实现 WebSocket 通信
- 1. 创建 Django 项目并安装依赖
- 2. 配置 ASGI 文件
- 3. 定义 WebSocket 路由
- 4. 创建 WebSocket Consumer
- 5. 在前端实现 WebSocket 连接
- 6. 启动 Daphne 服务器
- 🥇 高级功能
- 1. 广播消息给多个客户端
- 2. 使用 Redis 作为 Channel Layer 后端
- 📥 下载地址
- 💬 结语
- 📒 参考文献
🔨 Daphne 的主要特点
1. 支持 ASGI 协议
Daphne 作为 ASGI(Asynchronous Server Gateway Interface)服务器的实现,支持异步通信。ASGI 是 WSGI 的异步版本,它允许处理长连接、并发任务和实时通信,使得应用可以支持 WebSocket、HTTP2 和 HTTP/1.1。
2. 与 Django Channels 集成
Daphne 与 Django Channels 深度集成,Channels 扩展了 Django 的功能,支持 WebSocket、长轮询(Long Polling)、后台任务等异步操作,而 Daphne 则是这个异步处理的基础。通过将 Channels 和 Daphne 配合使用,开发者可以轻松为 Django 项目增加实时功能。
3. 多协议支持
Daphne 不仅支持标准的 HTTP/1.1,还支持 WebSocket 和 HTTP2。通过这些协议,Daphne 能够同时处理传统的 HTTP 请求和实时 WebSocket 连接,特别适合需要双向通信的应用场景,如实时聊天应用、在线协作工具或在线游戏。
4. 高性能异步处理
得益于 ASGI 协议的异步能力,Daphne 可以处理大量并发请求,尤其是在 WebSocket 长连接场景中,Daphne 的异步特性可以显著减少系统开销,提高应用的响应速度和并发处理能力。
📦 Daphne 的安装与使用
Daphne 的安装和使用非常简单,它与 Django 项目无缝集成。下面我们将展示如何在 Django 项目中安装和配置 Daphne。
1. 安装 Daphne
在 Django 项目中,使用 pip
来安装 Daphne:
pip install daphne
安装完成后,Daphne 将成为 Django 项目的默认异步服务器,用于处理异步请求。
2. 配置 ASGI 文件
在 Django 项目中,为了使用 Daphne 处理 WebSocket 或其他异步请求,我们需要配置 ASGI 应用。创建一个 asgi.py
文件,该文件用于定义项目的 ASGI 应用:
# asgi.py
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
import myapp.routing
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": AuthMiddlewareStack(
URLRouter(
myapp.routing.websocket_urlpatterns
)
),
})
在这个 asgi.py
文件中,我们使用 ProtocolTypeRouter
来处理多种协议。http
使用标准的 Django ASGI 应用处理 HTTP 请求,websocket
则配置了 WebSocket 的路由。
3. 配置 WebSocket 路由
接下来,配置 WebSocket 路由。在应用目录下创建 routing.py
文件,用于定义 WebSocket 的路由:
# myapp/routing.py
from django.urls import path
from . import consumers
websocket_urlpatterns = [
path('ws/chat/', consumers.ChatConsumer.as_asgi()),
]
这里定义了一个 WebSocket 路由 /ws/chat/
,当客户端与这个 URL 建立 WebSocket 连接时,会调用相应的 Consumer 处理 WebSocket 消息。
4. 创建 WebSocket Consumer
Consumer 是处理 WebSocket 消息的核心部分。在 myapp
应用中创建 consumers.py
文件,用于处理 WebSocket 的连接、接收消息等操作:
# myapp/consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
await self.accept()
async def disconnect(self, close_code):
pass
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
await self.send(text_data=json.dumps({
'message': message
}))
在这个 Consumer 中,我们实现了三个异步方法:
connect()
:当客户端连接时调用,并接受 WebSocket 连接。disconnect()
:处理连接关闭。receive()
:处理接收客户端发送的消息,并返回相同的消息给客户端。
5. 运行 Daphne 服务器
现在,我们已经配置好了 ASGI 应用、WebSocket 路由和 Consumer,可以使用 Daphne 运行项目了。通过以下命令启动 Daphne 服务器:
daphne -u /tmp/daphne.sock myproject.asgi:application
或者直接运行在本地开发模式下:
daphne myproject.asgi:application
Daphne 将开始监听异步请求并处理 WebSocket 连接。
🧱 应用场景
Daphne 与 Django Channels 配合,为 Django 项目提供了强大的异步支持,特别适合以下应用场景:
-
实时聊天应用:Daphne 通过 WebSocket 提供双向通信能力,可以轻松构建实时聊天应用,实现即时消息的发送和接收。
-
在线游戏:在线多人游戏中,玩家之间需要实时通信,Daphne 的高并发处理能力和 WebSocket 支持,使得开发实时互动的游戏成为可能。
-
协作工具:像 Google Docs 这样的在线协作工具需要多个用户同时编辑和查看文档。Daphne 的异步通信能力可以帮助构建实时同步的应用。
-
实时数据分析:数据流处理和实时更新的数据仪表盘需要即时更新数据,Daphne 能够处理这种高频率的数据推送需求。
♨️ 使用 Daphne 实现 WebSocket 通信
1. 创建 Django 项目并安装依赖
首先,创建一个新的 Django 项目,并安装所需的依赖项,包括 daphne
和 channels
:
django-admin startproject myproject
cd myproject
# 安装 Django Channels 和 Daphne
pip install channels daphne
接下来,编辑 myproject/settings.py
文件,将 channels
添加到 INSTALLED_APPS
,并指定 ASGI 应用:
# myproject/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels', # 添加 Channels 应用
]
# 指定 ASGI 应用
ASGI_APPLICATION = 'myproject.asgi.application'
2. 配置 ASGI 文件
在项目根目录下创建 asgi.py
文件,配置 ASGI 应用程序以支持 HTTP 和 WebSocket:
# myproject/asgi.py
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
import myapp.routing
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": AuthMiddlewareStack(
URLRouter(
myapp.routing.websocket_urlpatterns
)
),
})
3. 定义 WebSocket 路由
在应用中创建一个 routing.py
文件,用于定义 WebSocket 的路由。例如,在 myapp
应用下创建此文件并添加路由规则:
# myapp/routing.py
from django.urls import path
from . import consumers
websocket_urlpatterns = [
path('ws/chat/', consumers.ChatConsumer.as_asgi()),
]
这个路由配置表示,当用户访问 /ws/chat/
时,将会触发 ChatConsumer
处理 WebSocket 连接。
4. 创建 WebSocket Consumer
接下来,我们创建 WebSocket Consumer 来处理 WebSocket 的连接和消息。ChatConsumer
是一个异步 WebSocket 处理类,负责管理连接、接收消息和发送响应。
# myapp/consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
# 接受 WebSocket 连接
await self.accept()
async def disconnect(self, close_code):
# 处理连接关闭
pass
async def receive(self, text_data):
# 处理接收到的消息
text_data_json = json.loads(text_data)
message = text_data_json['message']
# 发送消息回客户端
await self.send(text_data=json.dumps({
'message': message
}))
ChatConsumer
包含三个主要的异步方法:
connect()
:当客户端尝试连接 WebSocket 时调用。通过accept()
接受连接。disconnect()
:当连接关闭时调用。receive()
:当接收到消息时调用,并通过send()
方法将响应消息发送回客户端。
5. 在前端实现 WebSocket 连接
为了与 WebSocket 进行通信,我们还需要在前端实现连接。以下是一个简单的 JavaScript 示例,用于连接 WebSocket 并发送/接收消息:
<!DOCTYPE html>
<html>
<head>
<title>Chat with WebSocket</title>
</head>
<body>
<h1>WebSocket Chat</h1>
<input type="text" id="messageInput" placeholder="Type a message..." />
<button onclick="sendMessage()">Send</button>
<ul id="messages"></ul>
<script>
const chatSocket = new WebSocket('ws://localhost:8000/ws/chat/');
chatSocket.onmessage = function(e) {
const data = JSON.parse(e.data);
const message = data.message;
const messagesList = document.getElementById('messages');
const newMessage = document.createElement('li');
newMessage.textContent = message;
messagesList.appendChild(newMessage);
};
function sendMessage() {
const messageInput = document.getElementById('messageInput');
const message = messageInput.value;
chatSocket.send(JSON.stringify({ 'message': message }));
messageInput.value = '';
}
</script>
</body>
</html>
在这个示例中,WebSocket
对象被用来连接后端的 WebSocket 路径 /ws/chat/
,并且通过 send()
方法发送消息,onmessage
回调函数用于接收来自后端的消息并将其显示在页面上。
6. 启动 Daphne 服务器
一切配置好后,使用 Daphne 来启动 Django 项目并处理异步请求。运行以下命令启动 Daphne:
daphne -p 8000 myproject.asgi:application
Daphne 服务器将启动并监听 HTTP 和 WebSocket 请求。
🥇 高级功能
1. 广播消息给多个客户端
如果你希望将一条消息广播给多个 WebSocket 连接的客户端,可以使用 Channels 的 ChannelLayer
。ChannelLayer
允许多个消费者在同一组内广播消息。以下是广播功能的实现:
修改 Consumer:
# myapp/consumers.py
from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_group_name = 'chat_room'
# 将连接加入到组
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
async def disconnect(self, close_code):
# 从组中移除连接
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
# 将消息发送到组
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'chat_message',
'message': message
}
)
async def chat_message(self, event):
message = event['message']
# 发送消息到 WebSocket
await self.send(text_data=json.dumps({
'message': message
}))
在这个例子中,当一个客户端发送消息时,receive()
方法会将消息广播到该组中的所有 WebSocket 连接。组内的所有连接都会收到相同的消息。
2. 使用 Redis 作为 Channel Layer 后端
为了支持横向扩展,Daphne 与 Channels 可以使用 Redis 作为消息队列(Channel Layer
)。安装 channels-redis
:
pip install channels-redis
在 settings.py
中配置 Redis 作为 Channel Layer
:
# myproject/settings.py
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('127.0.0.1', 6379)],
},
},
}
这样,多个 Daphne 实例可以通过 Redis 实现消息广播和同步处理。
📥 下载地址
Daphne 最新版 下载地址
💬 结语
Daphne 是 Django 生态中不可或缺的一部分,它为开发者提供了构建异步应用的能力,尤其是当你需要处理实时通信、WebSocket 或高并发任务时。通过与 Django Channels 配合,Daphne 不仅可以支持传统的 HTTP 请求,还可以处理更复杂的 WebSocket 和异步任务,为现代 Web 应用的开发提供了强大的支持。
如果你正在开发需要实时通信或高并发的 Django 应用,Daphne 是一个强大的工具,它可以帮助你轻松实现异步功能和高性能应用。
📒 参考文献
- Daphne GitHub仓库