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

在Elastic Beanstalk部署Django-Channels时WebSocket异常问题排查

问题:AWS Elastic Beanstalk部署Django应用WebSocket功能失效

背景

在AWS Elastic Beanstalk上部署Django应用,采用Gunicorn处理WSGI请求、Daphne处理ASGI请求。应用部署成功,但WebSocket功能无法正常工作。

Redis连接验证(结果正常)

通过以下步骤验证EC2实例与Redis缓存的连接:

eb ssh

source /var/app/venv/*/bin/activate
cd /var/app/current/
python manage.py shell

在Python Shell中执行:

import channels.layers
from asgiref.sync import async_to_sync
channel_layer = channels.layers.get_channel_layer()
async_to_sync(channel_layer.send)('test_channel', {'foo': 'bar'})
async_to_sync(channel_layer.receive)('test_channel')
# 成功收到响应:{'foo': 'bar'}

手动启动Daphne失败

在EC2实例执行启动命令:

daphne -b 0.0.0.0 -p 5000 tattoovalley.asgi:application

报错信息:

django.core.exceptions.ImproperlyConfigured: Requested setting INSTALLED_APPS, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.

已配置的.ebextensions文件

.ebextensions/01_env.config内容:

option_settings:  
    aws:elasticbeanstalk:environment:proxy:staticfiles:
        /static: static
        value: static/

    aws:elasticbeanstalk:container:python:     
        WSGIPath: tattoovalley/wsgi.py
    aws:elasticbeanstalk:application:environment:
        DJANGO_SETTINGS_MODULE: tattoovalley.settings
        PYTHONPATH: /opt/python/current/app/tattoovalley:$PYTHONPATH

    aws:elbv2:listener:80:
        DefaultProcess: http
        ListenerEnabled: 'true'
        Protocol: HTTP
        Rules: ws
    aws:elbv2:listenerrule:ws:
        PathPatterns: /ws/*
        Process: websocket
        Priority: 1
    aws:elasticbeanstalk:environment:process:http:
        Port: '80'
        Protocol: HTTP
    aws:elasticbeanstalk:environment:process:websocket:
        Port: '5000'
        Protocol: HTTP

端口检查结果

检查端口5000,未发现任何活动进程。

更新:ASGI配置文件内容

asgi.py文件:

import os
import django
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator
from django.core.asgi import get_asgi_application

from chat.routing import websocket_urlpatterns

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tattoovalley.settings")
django.setup()
django_asgi_app = get_asgi_application()

import chat.routing

application = ProtocolTypeRouter(
    {
        "http": django_asgi_app,
        "websocket": AllowedHostsOriginValidator(
            AuthMiddlewareStack(URLRouter(websocket_urlpatterns))
        ),
    }
)

问题排查与解决方案

1. 手动启动时加载环境变量

通过eb ssh进入实例后,Elastic Beanstalk配置的环境变量不会自动加载到当前Shell会话,需手动加载:

# 导出环境变量到临时文件
sudo /opt/elasticbeanstalk/bin/get-config environment | jq -r 'to_entries|map("\(.key)=\(.value)")|.[]' > /tmp/env.sh
source /tmp/env.sh

# 激活虚拟环境并启动Daphne
source /var/app/venv/*/bin/activate
cd /var/app/current/
daphne -b 0.0.0.0 -p 5000 tattoovalley.asgi:application

2. 配置Daphne为后台服务

Elastic Beanstalk默认仅管理Gunicorn进程,需配置让其自动启动Daphne。可添加.ebextensions/daphne.config:

container_commands:
  01_kill_existing_daphne:
    command: "pkill -f daphne || true"
  02_start_daphne:
    command: "nohup /var/app/venv/*/bin/daphne -b 0.0.0.0 -p 5000 tattoovalley.asgi:application > /var/log/daphne.log 2>&1 &"
    leader_only: true

或者用systemd配置持久化服务,创建.ebextensions/daphne.service.config:

files:
  "/etc/systemd/system/daphne.service":
    mode: "000644"
    owner: root
    group: root
    content: |
      [Unit]
      Description=Daphne ASGI Server for Django Channels
      After=network.target

      [Service]
      User=webapp
      WorkingDirectory=/var/app/current
      EnvironmentFile=/opt/elasticbeanstalk/deployment/env
      ExecStart=/var/app/venv/*/bin/daphne -b 0.0.0.0 -p 5000 tattoovalley.asgi:application
      Restart=always

      [Install]
      WantedBy=multi-user.target

container_commands:
  01_enable_daphne:
    command: "systemctl enable daphne.service"
  02_start_daphne:
    command: "systemctl start daphne.service"

3. 验证负载均衡器路由配置

在AWS控制台检查:

  • Elastic Beanstalk环境的负载均衡器HTTP 80端口监听器规则,确认/ws/*路径已指向websocket进程(端口5000)
  • 对应目标组的健康检查状态,确保实例5000端口可正常访问

4. 检查安全组配置

  • 确保EC2实例安全组允许来自ELB安全组的5000端口入站流量
  • 确保ELB安全组允许客户端的80/443端口入站流量(WebSocket基于HTTP/HTTPS协议)

5. 确认Django Channels配置正确性

确保settings.py中:

  • INSTALLED_APPS包含channels和channels_redis
  • CHANNEL_LAYERS配置正确指向Redis:
CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            "hosts": [('redis-endpoint', 6379)],
        },
    },
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 12:05:08