You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

部署Django Channels+Apache2+Daphne时WebSocket连接失败求助

Django Channels部署WebSocket连接失败排查

开发环境中使用Django Channels一切正常,但部署到本地服务器后出现问题。当前采用Apache2提供应用服务,将WebSocket请求转发至Daphne,页面可正常加载,但浏览器控制台提示WebSocket connection to 'wss://MYDOMAIN/ws/main/' failed:错误。以下是相关配置文件及排查建议:

Apache配置

<VirtualHost *:444>
        ServerName myDomain
        ServerAdmin admin
        DocumentRoot /var/www/thomasmichaelides/public_html

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        # Enable Websocket connections
        RewriteEngine on
        RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC,OR]
        RewriteCond %{HTTP:CONNECTION} ^Upgrade$ [NC]
        RewriteRule .* ws://127.0.0.1:8001%{REQUEST_URI} [P,QSA,L]

        Alias /static /home/atwebapps/arduinoDjango/static
        <Directory /home/atwebapps/arduinoDjango/static>
                Require all granted
        </Directory>

        <Directory /home/atwebapps/arduinoDjango/arduinoDjango>
                <Files wsgi.py>
                        Require all granted
                </Files>
        </Directory>
        WSGIScriptAlias / /home/atwebapps/arduinoDjango/arduinoDjango/wsgi.py
        WSGIDaemonProcess arduinoApp python-path=/home/atwebapps/arduinoDjango python-home=/home/atwebapps/arduinoDjango/venv
        WSGIProcessGroup arduinoApp

        SSLCertificateFile /etc/letsencrypt/live/mydomain/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/mydomain/privkey.pem
        Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>

daphne.service配置

[Unit]
Description=WebSocket Daphne Service
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/home/atwebapps/arduinoDjango
ExecStart=/home/atwebapps/arduinoDjango/venv/bin/python /home/atwebapps/arduinoDjango/venv/bin/daphne -b 0.0.0.0 -p 8001 arduinoDjango.asgi:application
Restart=on-failure

[Install]
WantedBy=multi-user.target

asgi.py文件

"""
ASGI config for arduinoDjango project.

It exposes the ASGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
"""

import os

from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'arduinoDjango.settings')

application = get_asgi_application()

settings.py中Channels相关配置

INSTALLED_APPS = [
    'main.apps.MainConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'channels',
    'corsheaders',
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

WSGI_APPLICATION = 'arduinoDjango.wsgi.application'
ASGI_APPLICATION = 'arduinoDjango.routing.application'
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("localhost", 6379)],
        },
    },
}

use_websockets = True

排查建议

  • 端口匹配检查:Apache的VirtualHost配置为*:444,但wss协议默认端口是443。确认前端请求的WebSocket URL是否包含:444端口(如wss://MYDOMAIN:444/ws/main/),或修改Apache配置为*:443以匹配默认SSL端口。
  • Apache模块启用检查:确保mod_proxy、mod_proxy_wstunnel和mod_ssl模块已启用,执行以下命令并重启Apache:
    a2enmod proxy proxy_wstunnel ssl
    systemctl restart apache2
    
  • ASGI配置修正:当前asgi.py仅返回Django的HTTP ASGI应用,未处理WebSocket请求。需修改asgi.py,引入Channels的路由处理逻辑:
    import os
    from django.core.asgi import get_asgi_application
    from channels.routing import ProtocolTypeRouter, URLRouter
    from channels.auth import AuthMiddlewareStack
    # 替换为你实际的路由模块路径
    from main.routing import websocket_urlpatterns
    
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'arduinoDjango.settings')
    
    application = ProtocolTypeRouter({
        "http": get_asgi_application(),
        "websocket": AuthMiddlewareStack(
            URLRouter(websocket_urlpatterns)
        ),
    })
    
    同时确认项目中存在routing.py文件,定义了WebSocket的URL路由规则。
  • Daphne服务状态检查:查看Daphne是否正常启动,执行:
    systemctl status daphne.service
    journalctl -u daphne.service -f
    
    确认端口8001被监听:
    netstat -tulpn | grep 8001
    
  • Redis服务检查:CHANNEL_LAYERS依赖Redis,确认Redis服务运行正常:
    systemctl status redis-server
    
    查看Daphne日志中是否有Redis连接失败的报错。
  • SSL配置验证:确认Apache的SSL证书路径正确,文件权限正常,mod_ssl模块已启用。
  • 日志分析:查看Apache的错误日志(${APACHE_LOG_DIR}/error.log)和访问日志,以及浏览器控制台的具体错误信息(如握手失败、超时等),定位更精确的问题原因。

内容的提问来源于stack exchange,提问作者Thomas Michaelides

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 09:22:09