微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Django Channels 2.4和Websockets在Elastic Beanstalk和ElastiCache上出现502错误

如何解决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 tutorialthis 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 举报,一经查实,本站将立刻删除。