将 Django 通道部署到 Elastic Beanstalk Python3.4 环境
Deploying Django Channels to Elastic Beanstalk Python3.4 environment
过去几天我一直在我的 Django 应用程序中实现 Channels,以便使用 Channel 的 websocket 支持。我的 Django 项目是用 Python 3.4 编写的,我正在使用 Daphne
和 Channel 的 redis
后端。
通过将 Supervisord 包装在 Python2 virtualenv 中并将其用于 运行 在 Python 中启动 Daphne/Redis/workers 的脚本,我已经能够在本地运行所有功能3 virtualenv,但未能成功部署到我们的 Elastic Beanstalk (Python 3.4) 环境。
有什么方法可以在 Python2 virtualenv 中将我的 EB 部署配置设置为 运行 Supervisor,就像我在本地可以做的那样?如果没有,我怎样才能让 Daphne、redis 和我的工作人员在 EB 部署上启动并 运行ning?如有必要,我愿意更换流程管理器,但发现 Supervisor 的语法比 Circus 更容易 understand/implement,并且我不知道任何其他可行的替代方案。
使用此配置,我能够成功部署到我的 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()
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 设置和基本主管配置。
感谢大家阅读本文,如果我可以通过 code/output 等方式提供任何其他信息,请告诉我
你说日志是空的,很难调试,确保在主监督配置文件中有日志行/etc/supervisord.conf
,看看错误是什么并分享它们。
[supervisord]
logfile=/var/log/supervisord/supervisord.log ; supervisord log file
loglevel=error ; info, debug, warn, trace
并且在你的 supervisor 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
因此,多亏了 Berlin 的回答中的日志记录建议,以及 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
仅此一项就足以让 Supervisor 运行ning 部署 EB,但我必须进行更多更改才能让 Daphne 和我的 Django worker 存活下来:
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 支持人员向我建议将 && source /opt/python/current/env
添加到 virtualenv 激活命令,因为环境变量不会自动拉入 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
我写了一篇很长很详细的 google 文档,说明如何在此处链接到它
https://docs.google.com/document/d/1naZsjO05Pa6uB9D-26eCeUVROZhz_MKkL8GI2knGLeo/edit?usp=sharing
对于任何版主,我没有在这里全部输入的原因是指南很长并且有很多图片。认为它值得分享,因为它会对某人有所帮助
过去几天我一直在我的 Django 应用程序中实现 Channels,以便使用 Channel 的 websocket 支持。我的 Django 项目是用 Python 3.4 编写的,我正在使用 Daphne
和 Channel 的 redis
后端。
通过将 Supervisord 包装在 Python2 virtualenv 中并将其用于 运行 在 Python 中启动 Daphne/Redis/workers 的脚本,我已经能够在本地运行所有功能3 virtualenv,但未能成功部署到我们的 Elastic Beanstalk (Python 3.4) 环境。
有什么方法可以在 Python2 virtualenv 中将我的 EB 部署配置设置为 运行 Supervisor,就像我在本地可以做的那样?如果没有,我怎样才能让 Daphne、redis 和我的工作人员在 EB 部署上启动并 运行ning?如有必要,我愿意更换流程管理器,但发现 Supervisor 的语法比 Circus 更容易 understand/implement,并且我不知道任何其他可行的替代方案。
使用此配置,我能够成功部署到我的 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()
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 设置和基本主管配置。
感谢大家阅读本文,如果我可以通过 code/output 等方式提供任何其他信息,请告诉我
你说日志是空的,很难调试,确保在主监督配置文件中有日志行/etc/supervisord.conf
,看看错误是什么并分享它们。
[supervisord]
logfile=/var/log/supervisord/supervisord.log ; supervisord log file
loglevel=error ; info, debug, warn, trace
并且在你的 supervisor 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
因此,多亏了 Berlin 的回答中的日志记录建议,以及 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
仅此一项就足以让 Supervisor 运行ning 部署 EB,但我必须进行更多更改才能让 Daphne 和我的 Django worker 存活下来:
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 支持人员向我建议将 && source /opt/python/current/env
添加到 virtualenv 激活命令,因为环境变量不会自动拉入 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
我写了一篇很长很详细的 google 文档,说明如何在此处链接到它
https://docs.google.com/document/d/1naZsjO05Pa6uB9D-26eCeUVROZhz_MKkL8GI2knGLeo/edit?usp=sharing
对于任何版主,我没有在这里全部输入的原因是指南很长并且有很多图片。认为它值得分享,因为它会对某人有所帮助