【问题标题】:Reload systemd/gunicorn/flask worker threads sequentially for config changes按顺序重新加载 systemd/gunicorn/flask 工作线程以进行配置更改
【发布时间】:2017-08-01 22:05:14
【问题描述】:

我需要强制重新加载应用以获取配置更改。我正在使用 systemd 来启动运行烧瓶应用程序的 gunicorn。

我在 /var/run/xx.conf 文件中获取配置更改,该文件由 systemd/service/app.path 监视:

[Path]
PathChanged=/var/run/app.conf

[Unit]
Description=app-restart

以及相应的app.system:

[Unit]
Description=app-restart
After=network.target

[Service]
Type=oneshot
PIDFile=/run/app-restart/pid
User=root
Group=root
ExecStart=/usr/bin/app-reload.py
PrivateTmp=false
EnvironmentFile=-/etc/environment

[Install]
WantedBy=multi-user.target

问题是——如何优雅地终止每个 gunicorn flask 工作线程?

应用的 systemd 服务使用:

[Unit]
Description=app gunicorn daemon
After=network.target

[Service]
PIDFile=/run/app/pid
User=ubuntu
Group=www-data
WorkingDirectory=/opt/app
ExecStart=/usr/local/bin/gunicorn --bind unix:/var/tmp/app.sock -m 007 --workers=2  -t 400 --backlog 2048 --log-config=/etc/app/log.cfg --log-level=DEBUG app
Restart=always
RestartSec=15
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
PrivateTmp=false
EnvironmentFile=-/etc/environment

[Install]
WantedBy=multi-user.target

这样我就可以杀死 gunicorn 工作线程并重新启动它们。

我想避免杀死正在处理响应的线程。

理想情况下,在处理完每个响应后,线程会检查它是否需要退出。我知道我可以在每个烧瓶 API 方法中执行此操作,但有没有更好的方法将所有工作线程一次转换到新配置?

我不想sysctl restart app.service,因为这会杀死所有线程并造成没有工作人员处于活动状态的死区时间。 我希望每个胎面都能独立终止和重新加载,这样总有一些活的工人。

我考虑过的一些选项:

  1. 使用 app-reload.py 获取应用程序 pid 列表,并一次将它们杀死一个。 Gunicorn 会在它死后重新启动。可以终止正在进行的请求。

  2. 处理完每个事件后,检查由 app-reload.py 创建的文件是否存在,如果存在,则终止。

我假设必须有一种方法可以将工作人员从一个配置迁移到另一个配置,而不会造成服务死点。

【问题讨论】:

    标签: python flask gunicorn systemd


    【解决方案1】:

    RTM 再次获胜。

    http://docs.gunicorn.org/en/stable/signals.html

    HUP:重新加载配置,启动新的工作进程 新配置并优雅地关闭老员工。如果 应用程序未预加载(使用 preload_app 选项),Gunicorn 也会加载它的新版本。

    所以最终结果就是systemd app.path中的这个:

    [Unit]
    Description=app-restart
    After=network.target
    
    [Service]
    Type=oneshot
    User=root
    Group=root
    ExecStart=/bin/kill -s HUP $(cat /run/app/pid)
    PrivateTmp=false
    

    或者,也可以依赖 app.system 包含一个 ExecReload 行并使用这一事实:

    ExecReload=/bin/systemctl reload app
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-04
      • 2018-05-05
      • 2016-07-20
      • 2017-12-02
      • 2013-04-22
      • 2019-09-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多