在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_redisCHANNEL_LAYERS配置正确指向Redis:
CHANNEL_LAYERS = { 'default': { 'BACKEND': 'channels_redis.core.RedisChannelLayer', 'CONFIG': { "hosts": [('redis-endpoint', 6379)], }, }, }
内容的提问来源于stack exchange,提问作者paul
相关产品推荐
相关产品推荐

