【问题标题】:Deploying Django Channels to Elastic Beanstalk Python3.4 environment将 Django 通道部署到 Elastic Beanstalk Python3.4 环境
【发布时间】:2017-10-12 07:50:13
【问题描述】:

过去几天我一直在我的 Django 应用程序中实现 Channels,以便使用 Channel 的 websocket 支持。我的 Django 项目是用 Python 3.4 编写的,我使用的是 Daphne 和 Channel 的 redis 后端。

通过将 Supervisord 包装在 Python2 virtualenv 中并使用它运行在 Python3 virtualenv 中启动 Daphne/Redis/workers 的脚本,我已经能够让所有东西在本地运行,但没有成功部署到我们的 Elastic Beanstalk(Python 3.4 ) 环境。

有什么方法可以设置我的 EB 部署配置以在 Python2 virtualenv 中运行 Supervisor,就像我可以在本地一样?如果没有,我该如何让 Daphne、redis 和我的工作人员在 EB 部署上启动并运行?如有必要,我愿意切换流程管理器,但发现 Supervisor 的语法比 Circus 更容易理解/实现,并且不知道有任何其他可行的替代方案。

使用此配置,我能够成功部署到我的 EB 环境并通过 ssh 进入其中,但 Supervisor 无法启动每个进程,如果我尝试手动启动 Supervisor 以检查进程 supervisorctl status 会给我 @987654325 @我尝试初始化的所有内容。日志是空的。

频道后端配置:

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "asgi_redis.RedisChannelLayer",
        "ROUTING": "<app>.routing.channel_routing",
        "CONFIG": {
            "hosts": [
                os.environ.get('REDIS_URL', 'redis://localhost:6379')
            ],
        },
    },
}

asgi.py:

import os
from channels.asgi import get_channel_layer

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "<app>.settings")

channel_layer = get_channel_layer()

supervisor conf(conf 文件的其余部分保持默认):

[program:Redis]
environment=PATH="/opt/python/run/venv/bin"
command=sh /opt/python/current/app/<app>/start_redis.sh
directory=/opt/python/current/app
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/tmp/redis.out.log

[program:Daphne]
environment=PATH="/opt/python/run/venv/bin"
command=sh /opt/python/current/app/<app>/start_daphne.sh
directory=/opt/python/current/app
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/tmp/daphne.out.log

[program:Worker]
environment=PATH="/opt/python/run/venv/bin"
command=sh /opt/python/current/app/<app>/start_worker.sh
directory=/opt/python/current/app
process_name=%(program_name)s_%(process_num)02d
numprocs=4
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/tmp/workers.out.log

.ebextensions/channels.config:

container_commands:
  01_start_supervisord:
    command: "sh /supervisord/start_supervisor.sh"

start_supervisor.sh:

#!/usr/bin/env bash
virtualenv -p /usr/bin/python2.7 /tmp/senv
source /tmp/senv/bin/activate
sudo pip install supervisor
sudo /usr/local/bin/supervisord -c 
/opt/python/current/app/<app>/supervisord.conf
supervisorctl -c /opt/python/current/app/<app>/supervisord.conf status

start_redis:

#!/usr/bin/env bash
sudo wget http://download.redis.io/releases/redis-3.2.8.tar.gz
sudo tar xzf redis-3.2.8.tar.gz
cd redis-3.2.8
sudo make
source /opt/python/run/venv/bin/activate
sudo src/redis-server

start_daphne:

#!/usr/bin/env bash
source /opt/python/run/venv/bin/activate
/opt/python/run/venv/bin/daphne -b 0.0.0.0 -p 5000 <app>.asgi:channel_layer

start_worker:

#!/usr/bin/env bash
source /opt/python/run/venv/bin/activate
python manage.py runworker

我大致关注this guide,但由于它是为 python2 EB 环境编写的,它实际上只适用于 ALB 设置和基本主管配置。

感谢大家阅读本文,如果我可以通过代码/输出等方式提供任何其他内容,请告诉我。

【问题讨论】:

  • 提醒任何打算这样做的人,请注意,在自动缩放 EB 环境中,已建立的 websocket 有可能在 EC2 实例死亡/存在时不会收到 sigkill 或其他信号旋转下来。由于 websocket 连接在保持打开状态时突然没有响应,这给我们的前端带来了很多麻烦。我已经关闭了该项目并且无法提供解决方案,但想指出它可能会为某人节省一些痛苦。

标签: django python-3.x amazon-elastic-beanstalk supervisord django-channels


【解决方案1】:

因此,感谢 Berlin 的回答提供的日志记录建议,以及 AWS 支持团队建议的虚拟环境调整(我将这个问题转发给了他们),我终于能够让它发挥作用。

首先,我最终从 Supervisor 中完全删除了 Redis,而是选择运行一个 ElastiCache Redis 实例,然后将其连接到我的 EB 实例。我不认为这是处理此问题的唯一方法,但这是我实施的最佳途径。

然后,我不再使用预先存在的 start_supervisor.sh 脚本,而是向 channels.config ebextension 添加了一个命令,以创建脚本并将其添加到 EB 的部署后操作中。这是必要的,因为.ebextension 配置文件在部署期间运行,但不会在环境创建之前存在(这可能不完全正确,但为了这个解决方案,这就是我对它们的看法),所以即使我的脚本大部分是正确的,它启动的主管进程会在部署完成后立即终止。

所以我的.ebextensions/channels.config 现在是:

container_commands:
  01_create_post_dir:
    command: "mkdir /opt/elasticbeanstalk/hooks/appdeploy/post"
    ignoreErrors: true
files:
  "/opt/elasticbeanstalk/hooks/appdeploy/post/start_supervisor.sh":
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/usr/bin/env bash
      virtualenv -p /usr/bin/python2.7 /tmp/senv
      source /tmp/senv/bin/activate && source /opt/python/current/env
      python --version > /tmp/version_check.txt
      sudo pip install supervisor
      /usr/local/bin/supervisord -c /opt/python/current/app/<app>/supervisord.conf
      supervisorctl -c /opt/python/current/app/<app>/supervisord.conf status

仅此一项就足以让 Supervisor 在 EB 部署上运行,但我必须进行更多更改才能让 Daphne 和我的 Django 工作人员保持活力:

start_daphne.sh:

#!/usr/bin/env bash
source /opt/python/run/venv/bin/activate && source /opt/python/current/env
/opt/python/run/venv/bin/daphne -b 0.0.0.0 -p 5000 <app>.asgi:channel_layer

start_worker.sh:

#!/usr/bin/env bash
source /opt/python/run/venv/bin/activate && source /opt/python/current/env
python manage.py runworker

AWS 支持向我建议将 &amp;&amp; source /opt/python/current/env 添加到 virtualenv 激活命令,因为 env 变量不会自动拉入 virtualenvs,这导致 Daphne 和工作人员因导入错误而在创建时死亡。

我还对我的supervisord.conf 文件进行了一些更改:

[unix_http_server]
file=/tmp/supervisor.sock   ; (the path to the socket file)

[supervisord]
logfile=/tmp/supervisord.log ; supervisord log file
loglevel=error ; info, debug, warn, trace
logfile_maxbytes=50MB        ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10           ; (num of main logfile rotation backups;default 10)
pidfile=/tmp/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=false               ; (start in foreground if true;default false)
minfds=1024                  ; (min. avail startup file descriptors;default 1024)
minprocs=200                 ; (min. avail process descriptors;default 200)

; the below section must remain in the config file for RPC
; (supervisorctl/web interface) to work, additional interfaces may be
; added by defining them in separate rpcinterface: sections
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL  for a unix socket

[program:Daphne]
environment=PATH="/opt/python/run/venv/bin"
command=sh /opt/python/current/app/<app>/start_daphne.sh --log-file /tmp/start_daphne.log
directory=/opt/python/current/app
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/tmp/daphne.out.log
stderr_logfile=/tmp/daphne.err.log

[program:Worker]
environment=PATH="/opt/python/run/venv/bin"
command=sh /opt/python/current/app/<app>/start_worker.sh --log-file /tmp/start_worker.log
directory=/opt/python/current/app
process_name=%(program_name)s_%(process_num)02d
numprocs=4
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/tmp/workers.out.log
stderr_logfile=/tmp/workers.err.log

【讨论】:

  • 如何在settings.py中设置redis主机端点地址?我尝试使用 GetAtt 抓取端点地址,将其放入 env,然后让 django 抓取。但它不起作用。
  • 如果您可以分享您的 ebextension 配置文件 :)
  • @MarshallX 用于 redis 主机端点 我通过 AWS 控制台(在 ElastiCache 下)找到了我的 Redis 服务器的 primary endpoint,并将其设置为我在 settings.py 中获取的环境变量。上面已经包含了所有相关的配置文件。
  • 我也采用了同样的方法。想知道我是否可以从 env 中获取端点 url。
【解决方案2】:

你说日志是空的,很难调试,请确保在主主管配置文件/etc/supervisord.conf 上有日志行,查看错误并分享它们。

[supervisord]
logfile=/var/log/supervisord/supervisord.log ; supervisord log file
loglevel=error ; info, debug, warn, trace

并在您的主管 conf 文件中为您的每个程序添加一个日志错误并查看错误并分享它们。

command=sh /opt/python/current/app/<app>/start_redis.sh --log-file /path/to/your/logs/start_redis.log
stdout_logfile=/tmp/redis.out.log
stderr_logfile=/tmp/redis.err.log

【讨论】:

    【解决方案3】:

    我写了一篇长而详细的谷歌文档,说明如何在此处链接到它

    https://docs.google.com/document/d/1naZsjO05Pa6uB9D-26eCeUVROZhz_MKkL8GI2knGLeo/edit?usp=sharing

    对于任何版主来说,我没有在这里全部输入的原因是该指南很长并且有很多图像。认为它值得分享,因为它会帮助某人

    【讨论】:

    • @Manhattan 博士,感谢链接的 google 文档中的精彩文章,您能否谈谈生产中的 redis 服务器/redis,例如 Ec2 中的 ELASTICACHE。提前致谢。
    • 说什么@ray 大声笑,你需要更具体。您在生产中使用 redis 时遇到什么问题?
    • 感谢和抱歉迟到的回复。
    • 感谢和抱歉迟到的回复。经过一番研究,我得到了redis。这是我的担忧,在我的本地机器上,我有一个来自浏览器 JavaScript 客户端的工作端点:: const client = new W3WebSocket(ws://localhost:8000/ws/chat/)。这就是在客户端上定义连接的方式。我想知道我是否必须从 URL 中删除“ws”并将其更改为 elasticbeanstalk 中的 http/https 。即 const client = new W3WebSocket(http://localhost:8000/ws/chat/)。谢谢,希望收到您的来信。
    • 没有。 wss 协议通过加密的 TLS 连接建立 WebSocket,而 ws 协议使用未加密的连接。阅读本文以获得更清晰的信息:stackoverflow.com/questions/46557485/…
    猜你喜欢
    • 2016-04-20
    • 2020-03-24
    • 2017-04-07
    • 2017-12-27
    • 2015-10-23
    • 2016-07-18
    • 1970-01-01
    • 2015-07-05
    • 2020-10-08
    相关资源
    最近更新 更多