【发布时间】:2018-02-16 12:35:02
【问题描述】:
情况:我想将我们 Django 项目的代码更改部署到舞台或生产服务器。为此,我们有一个 ansible 部署脚本,它从 gitlab 中提取 django 项目的代码、迁移数据库、收集静态文件、重新启动不同的服务器等。
问题:当我通过 ansible 脚本部署时,一些 uwsgi 进程(平均 10 个中的 1 个)不会重新加载我的 django 应用程序。例如,在代码更新后静态资产更改并且静态资产包的文件名散列更改后,我可以重现这一点。然后服务器抛出 500 错误,因为 uwsgi 仍然尝试使用旧哈希加载捆绑包(通过https://github.com/ezhome/django-webpack-loader)。当我在静态资产发生更改的部署后在浏览器中刷新网站时,服务器在大约 10-20% 的请求中返回 500 错误,因为它找不到旧的静态资产包(例如:bundle.9290aAFKASE234. js)。
当我在服务器上运行/etc/init.d/supervisor restart 时,问题立即消失,所有 uwsgi 进程似乎都已正确重新加载。
相关的nginx配置
location / {
{% if nginx_site_basic_auth %}
auth_basic "Test Server what.digital";
auth_basic_user_file "{{ project_root}}/nginx_passwdfile";
{% endif %}
uwsgi_pass {{ project_name }}_server;
uwsgi_read_timeout 1800s;
include /etc/nginx/uwsgi_params;
}
uwsgi 配置(app.ini)
# uwsgi.ini file
[uwsgi]
# Django-related settings
# the base directory (full path)
chdir = {{ project_root }}
# Django's wsgi file
module = {{ project_django_wsgi }}
plugins = python
# the virtualenv (full path)
home = {{ project_venv }}
# process-related settings
# prevents some pretty crazy erratic behaviour
lazy-apps = true
# master
master = true
# maximum number of worker processes
processes = 10
pidfile = {{ wsgi_pid_file }}
#touch-reload = {{ project_root }}/config/wsgi.py
#daemonize = {{ project_root }}/{{ project_name }}-uwsgi-daemon.log
logto = {{ project_root }}/{{ project_name }}-uwsgi-error.log
log-5xx = true
disable-logging = true
harakiri = 120
no-orphans = true
max-requests = 50
# give appropriate permissions to socket file
chmod-socket = 666
# the socket (use the full path to be safe)
socket = {{ project_root }}/{{ project_name }}.sock
# http-socket = :8000
# clear environment on exit
vacuum = true
buffer-size = 32768
# https://stackoverflow.com/questions/32452529/uwsgi-emperor-unicodeencodeerror-ascii-codec-cant-encode-character
env = LANG=en_US.UTF-8
主管模板(由ansible填充):
[program:uwsgi]
user = {{ user_name }}
command={{ project_venv }}/bin/uwsgi --ini {{ project_root }}/{{ uwsgi_conf_file }}
environment={% for name, value in env_vars.iteritems() -%}
{{ name }}="{{ value|replace('%', '%%') }}";
{%- endfor %}
autostart=true
autorestart=true
stderr_logfile = {{ project_logs }}/supervisor_uwsgi_err.log
stdout_logfile = {{ project_logs }}/supervisor_uwsgi_stdout.log
stopsignal=INT
相关的ansible配置
- name: upload supervisor configuration
template: src=supervisor.j2 dest=/etc/supervisor/conf.d/{{ project_name }}.conf
become_user: root
#- name: make sure supervisord runs
# service: name=supervisor state=started
# become_user: root
#- name: reread supervisorctl config files
# command: supervisorctl reread
# become_user: root
- name: restart supervisor
# ansible's supervisorctl module doesnt really restart and some weird caching problems emerge
# shell: supervisorctl restart uwsgi
shell: /etc/init.d/supervisor restart
become_user: root
- name: make sure nginx is restarted
service: name=nginx state=restarted
become_user: root
【问题讨论】:
-
你运行
supervisorctl restart uwsgi吗?它已在您的 ansible 文件中注释掉。 -
json 文件不像 python 文件那样工作。一旦文件被修改,更改就会生效。重启uwsgi没关系。如果您想要不同的行为,您可能必须以某种方式更改 django-webpack-loader。例如,应该可以将 json 文件转换为公开字典的 python 脚本。然后,这将由 uwsgi 工人兑现。
-
也可以更改 django-webpack-loader 配置以获得相同的结果。你启用缓存了吗? github.com/ezhome/django-webpack-loader#cache
-
如果在运行 Ansible 后直接在服务器上调用
/etc/init.d/supervisor restart可以解决问题,则问题可能是您的 Ansible 配置的一部分。你所展示的 Ansible 配置是否 100% 与 Supervisor 相关? -
@HåkenLid 谢谢,/etc/init.d/supervisor restart 也会重新启动所有子进程 AFAIK。关于 json 文件,这是预期的行为。但是一旦主管重新启动了 uwsgi 进程,它也应该捕获 json 文件中的新路径。问题恰恰相反,uwsgi 仍然从 json 文件中“读取”旧路径。它还从 db.sqlite3 数据库文件中“读取”旧值!它似乎以某种方式缓存进程有权访问的文件。