Django WebSocket 核心:Channels 与 Daphne 详解

2026-01-20 09:48:43 by wst

web开发

接上一篇文章:django中实现websocket通信,深入了解 Channels 和 Daphne 这两个核心组件的作用、原理以及它们和 Django 的关系,这是理解 Django 实现 WebSocket 功能的关键,下面用通俗易懂的方式进行说明。

核心背景:Django 的「先天不足」

Django 最初专为 HTTP 请求 设计,而 HTTP 是无状态、单向、短连接的协议:

客户端(浏览器)发请求 → 服务端处理 → 返回响应 → 连接断开

服务端无法主动给客户端推送消息,因此传统 Django 无法实现实时聊天、实时数据推送等功能。

要实现 WebSocket(双向、长连接、实时通信),需解决两个核心问题:

  1. 让 Django 能处理异步的、长连接的 WebSocket 请求(而非一次性 HTTP 请求)
  2. 配备能处理异步请求的服务器(传统 WSGI 服务器仅支持同步 HTTP)

Channels + Daphne 正是为解决这两个问题而生。


一、Daphne 4.2.1:处理异步请求的 ASGI 服务器

1. 核心定义

Daphne 是异步的 ASGI 服务器(ASGI = Asynchronous Server Gateway Interface,异步服务器网关接口),作为客户端请求与 Django 应用的「桥梁」,专门处理:

  • 传统 HTTP 请求(兼容 WSGI)
  • 异步 WebSocket 请求
  • 异步 HTTP2 请求

2. 为什么需要它?

传统 Django 使用 WSGI 服务器(如 Gunicorn、uWSGI),但 WSGI 是同步的,仅支持「请求-响应」式短连接,无法处理 WebSocket 长连接、双向通信。

而 Daphne 作为 ASGI 服务器,天生支持异步和长连接:

  • 客户端发起 WebSocket 连接后,Daphne 保持连接不中断
  • 服务端可随时通过连接推送消息给客户端
  • 客户端也可随时给服务端发消息

3. 通俗类比

组件 角色描述
WSGI 服务器 只能接「一次性点餐」的服务员(点完单就走,无法持续沟通)
Daphne 既能接一次性点餐,又能陪客人「实时聊天」的服务员(连接持续保持,随时响应)

4. 实际使用

项目中启动 Django 时,Daphne 会作为默认服务器运行(因配置了 ASGI):

# 启动命令(底层实际是 Daphne 运行)
python manage.py runserver

 

生产环境推荐单独启动 Daphne:

daphne -p 8000 wsdemo.routings.application

 


二、Channels 4.3.2:给 Django 扩展 WebSocket 能力

1. 核心定义

Channels 是 Django 官方扩展库,在原有功能基础上新增对 异步通信协议 的支持(核心是 WebSocket),让 Django 能像处理 HTTP 请求一样处理 WebSocket 请求。

2. Channels 核心组成(新手重点)

Channels 将 WebSocket 处理逻辑拆分为 3 个核心部分,对应项目配置:

(1) 路由(Routing)

与 Django 的 urls.py 对应,专门映射 WebSocket 请求路径到处理逻辑。
示例(wsdemo/dish/routing.py):

from django.urls import re_path
from . import consumers

websocket_urlpatterns = [
    # 聊天功能:映射 /ws/chat/房间名/ 到 ChatConsumer
    re_path(r'ws/chat/(?P<room_name>\w+)/$', consumers.ChatConsumer.as_asgi()),
    # 桌子状态:映射 /ws/abc/ 到 TableStatusConsumer
    re_path(r'ws/abc/$', consumers.TableStatusConsumer.as_asgi()),
]

作用:告诉 Django「哪个 WebSocket 路径该由哪个代码处理」。

(2) 消费者(Consumer)

与 Django 的 View(视图)对应,是处理 WebSocket 逻辑的核心代码。
消费者可处理 WebSocket 4 个核心事件:

  • connect():客户端建立连接时触发
  • disconnect():客户端断开连接时触发
  • receive():服务端收到客户端消息时触发
  • send():服务端主动给客户端推送消息时调用

简化示例:

from channels.generic.websocket import AsyncWebsocketConsumer
import json

class SimpleChatConsumer(AsyncWebsocketConsumer):
    # 建立连接时
    async def connect(self):
        # 加入「房间」(用于多客户端广播)
        self.room_name = "my_chat_room"
        await self.channel_layer.group_add(self.room_name, self.channel_name)
        # 接受客户端连接
        await self.accept()

    # 断开连接时
    async def disconnect(self, close_code):
        await self.channel_layer.group_discard(self.room_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_name,
            {
                'type': 'chat_message',  # 对应下方 chat_message 方法
                'message': message
            }
        )

    # 处理广播消息
    async def chat_message(self, event):
        message = event['message']
        # 给客户端发送消息
        await self.send(text_data=json.dumps({
            'message': message
        }))

 

(3) 通道层(Channel Layer)

Channels 实现多客户端通信的关键(项目中用 Redis 作为通道层)。

  • 作用:实现不同消费者之间的通信(如将一个客户端的消息广播给所有客户端)
  • 为什么用 Redis:内存数据库速度快,支持发布/订阅模式,可跨进程/跨服务器传递消息

项目配置示例(settings.py):

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            'hosts': ["redis://:t123entzzzt@141.142.150.132:6378/1"]
        }
    }
}

 

3. Channels 工作流程(结合项目聊天功能)

  1. 客户端(User1)访问 one.html,前端通过 new WebSocket('ws://127.0.0.1:8000/ws/chat/302/') 发起连接
  2. Daphne 接收 WebSocket 请求,通过 ASGI 传递给 Channels
  3. Channels 匹配路由,找到 ChatConsumer,执行 connect() 方法,将客户端加入「302」房间(Redis 组)
  4. User1 发送消息 → 前端 JSON 化后通过 WebSocket 发送 → 服务端 receive() 方法接收
  5. receive() 通过 Redis 通道层,将消息广播到「302」房间所有客户端
  6. User2(已连接同房间)的消费者收到广播,通过 send() 推送给 User2 前端
  7. User2 前端 onmessage 监听事件触发,显示消息

三、Channels + Daphne + Django 关系总结

层级逻辑(文字版)

客户端(浏览器)
    ↓ ↑(WebSocket 双向通信)
Daphne(ASGI 服务器):接收/转发异步请求
    ↓ ↑
Channels(Django 扩展):
    - 路由:映射 WebSocket 路径到消费者
    - 消费者:处理 WebSocket 逻辑
    - 通道层(Redis):多客户端消息通信
    ↓ ↑
Django 核心:处理数据库、用户认证等原有功能

 

核心总结

  1. Daphne 是「异步服务器」,解决传统 WSGI 服务器无法处理 WebSocket 长连接的问题,是客户端与 Django 的入口;
  2. Channels 是「Django 扩展」,新增 WebSocket 处理能力,核心通过「路由 + 消费者 + 通道层」实现实时通信;
  3. 两者配合,让原本仅支持同步 HTTP 的 Django 具备了异步 WebSocket 实时通信能力,这也是项目能实现实时聊天、桌子状态推送的核心原因。

 


Comments(0) Add Your Comment

Not Comment!