如何解决Django Channels 2.4和Websockets在Elastic Beanstalk和ElastiCache上出现502错误
我已通过django渠道将聊天组件集成到django网络应用程序中,其方式与记录的here非常相似。我用elasticache创建了我的redis实例。我的settings.py如下所示:
Asgi_APPLICATION = 'MyApp.routing.application'
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer','CONfig': {
"hosts": [('my-redis-instance.cache.amazonaws.com',6379)],#This is a placeholder in the question for the cluster's actual endpoint
},},}
在将我的应用程序部署到弹性beantalk时,我尝试遵循this tutorial和this tutorial并没有碰到运气。我的django.config文件当前如下所示:
container_commands:
01_collectstatic:
command: "source /opt/python/run/venv/bin/activate && python manage.py collectstatic --noinput"
02_migrate:
command: "django-admin.py migrate"
leader_only: true
03_load-data:
command: "python manage.py load_database"
leader_only: true
option_settings:
aws:elasticbeanstalk:application:environment:
DJANGO_SETTINGS_MODULE: MyApp.settings
aws:elasticbeanstalk:container:python:
WsgiPath: MyApp/wsgi.py
"aws:elasticbeanstalk:container:python:staticfiles":
/static/: "static/"
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
我还尝试创建procfile来配置gunicorn和daphne。看起来像这样:
web: gunicorn --bind :8000 --workers 3 --threads 2 MyApp.wsgi:application
websocket: daphne -b 0.0.0.0 -p 5000 MyApp.asgi:application
附加到我的ElastiCache redis实例的安全组具有入站规则,其中“自定义TCP”设置为端口6379,源设置为“任意”。在尝试所有这些不同的部署方法时,我继续遇到以下错误:
[Error] WebSocket connection to 'ws://my-site-url.com/ws/messages/' Failed: Unexpected response code: 502
我不确定该怎么办。我已经看到了几个与此相关的堆栈溢出帖子,但是都没有帮助。这个post似乎有一个有效的解决方案,但我认为它已经过时了。
更新:
在进行更多搜索时,我在.ebextensions文件夹中创建了一个websockets-python.config文件,该文件应该配置Apache代理服务器以允许使用Web套接字。我还删除了配置daphne和Gunicorn的procfile。 websockets-python.config文件如下所示:
files:
"/etc/httpd/conf.d/proxy-pass.conf":
mode: "000644"
owner: root
group: root
content: |
ProxyPass /ws/ ws://127.0.0.1:5000/
ProxyPassReverse /ws/ ws://127.0.0.1:5000/
"/etc/httpd/conf.modules.d/99-mod_proxy_wstunnel.conf":
mode: "000644"
owner: root
group: root
content: |
<IfModule !proxy_wstunnel_module>
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
</IfModule>
重新部署此文件后,我在Web套接字上收到无效状态错误,然后Web套接字连接最终超时。我认为该Web套接字正在尝试连接,但是由于某种原因(也许是我的安全组的配置方式)无法连接,然后最终超时。
安全组配置:
ELB:端口80上任意位置的入站规则。端口80和5000到任意位置的出站规则
我的服务器:来自ELB的端口80和5000上的入站规则。所有到任何地方的流量的出站规则。
ElastiCache实例:端口6379的入站规则来自任何位置,端口6439的入站规则来自服务器。所有流量到任何地方的出站规则。
解决方法
~~使用ElastiCache时,必须使用群集的主要端点。您可以转到ElastiCache的仪表板,转到Redis,然后单击下拉列表。找到主要端点并使用它代替my-redis-instance.cache.amazonaws.com
~~
编辑,因为端点可能只是正确的:问题可能出在ElastiCache上的安全组中。 ElastiCache群集应仅允许来自服务器SG的入站(在端口6439上),后者仅允许来自ELB的安全组的入站(在端口5000上?),后者仅允许从任何位置从端口443和端口80入站。
最后,我发现配置Gunicorn和Daphne很奇怪。除了Daphne可以运行ASGI以外,它们不是同一个人吗? (只有具有Gunicorn的Uvicorn工作者才能使用ASGI;您应该仅使用Daphne而不启用Gunicorn。)
从理论上讲,这一切都表明您的AWS实例具有足够的内存和CPU。那也可能是一个问题。我建议开发人员使用Sentry(免费),以便您看看。我的502个错误中有很多都因为一些整洁的错误而得到解决。
,经过几天的工作,我找到了解决方案。我无法使负载平衡器上的端口转发正常工作,但是我将我的端口配置为转发到Nginx上的端口5000。
redis网址:
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer","CONFIG": {
"hosts": [(REDIS_URL,6379)],},}
Nginx配置:
.platform / nginx / nginx.conf
#Elastic Beanstalk Nginx Configuration File
user nginx;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 32137;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
include conf.d/*.conf;
map $http_upgrade $connection_upgrade {
default "upgrade";
}
server {
listen 80 default_server;
access_log /var/log/nginx/access.log main;
client_header_timeout 60;
client_body_timeout 60;
keepalive_timeout 60;
gzip off;
gzip_comp_level 4;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
# Include the Elastic Beanstalk generated locations
include conf.d/elasticbeanstalk/*.conf;
location /ws {
proxy_pass http://127.0.0.1:5000;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}
}
}
Procfile:
web: gunicorn --bind 127.0.0.1:8000 --workers=1 --threads=15 project.wsgi:application
websocket: daphne -b 0.0.0.0 -p 5000 project.asgi:application
对于安全组,在创建Redis时,需要在安全组上的入站目标字段中添加EC2实例上当前正在使用的安全组的ID。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。