将Django频道部署到Elastic Beanstalk Python3.4环境

时间:2017-05-12 22:07:18

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

我花了几天时间将频道实现到我的Django应用程序中,以便使用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给了我我尝试初始化的所有内容都FATAL "Exited too quickly (process log may have details)。日志是空的。

频道后端配置:

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()

主管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设置和基本管理程序配置有用。

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

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:2)

感谢柏林的回答提供的日志记录建议,以及AWS支持团队建议的虚拟环境调整(我将这个问题转发给他们),我终于能够实现这一点。

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

然后我改变了使用预先存在的start_supervisor.sh脚本,而是向channels.config ebextension添加了一个命令来创建脚本并将其添加到EB的部署后操作中。这是必要的,因为.ebextension配置文件在部署期间运行,但不会过去环境创建(这可能不完全正确,但为了解决这个问题,我想到它们),所以即使我的脚本大多是正确的,它启动的Supervisor进程只要在部署完成后就会死掉。

所以我的.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

仅此一点就足以让主管在EB部署上运行,但我必须做出一些更改才能让达芙妮和我的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支持人员向我建议在virtualenv激活命令中添加&& source /opt/python/current/env,因为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

答案 2 :(得分:0)

我写了一个长而详细的谷歌文档,关于如何在此处链接到它

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

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