Python Supervisord程序依赖性

36

我在我的supervisord.conf中有[program:A][program:B]

B依赖于A,也就是说:

A应该在B之前启动。

如何通过supervisor来确保这一点?


可能值得一看 ordered-startup-supervisord - 3k-
4个回答

34

supervisord 不直接支持依赖关系。你的选项是:

  • 使用优先级。将 Apriority 设置为一个较低的值,它会在 B 之前启动,并在 B 之后关闭。 priority 的默认值为 999

    如果你将这两个程序放在同一组中,那么你可以同时启动和停止它们,通过优先级来调节它们的启动和停止顺序。

  • 编写一个事件监听器来监听 APROCESS_STATESTARTINGRUNNING 的转换以及 STOPPING 事件,然后根据这些事件指示 supervisord 启动和停止 B。让 A 自动启动,但对于 B 禁用自动启动,以便事件处理程序控制它。


10
我理解上述的“优先级”方法很可能不会按预期工作。Supervisord确实会按顺序启动进程,但例如,在启动进程B之前,它不会等待进程A完全启动(也就是说,Supervisord会忽略startsecs参数)。相反,它会立即在A之后启动B,这在许多情况下都不是你想要的(足够的)。这种行为已经在2012年被报告过,但截至2014年仍未得到修复。 - miguno
@miguno:那么您的选择是使用事件监听器。 - Martijn Pieters
@Cheche:优先级工作得很好,但是如果您希望优先级顺序也包括等待,直到更高优先级的程序达到运行状态,那么这种期望将会失望。请注意,迈克尔已经在6年前链接到了同样的问题。 - Martijn Pieters
@MartijnPieters 有趣... 没有注意到。所以优先级只是启动延迟的问题吗? - Cheche
@Cheche:是的,没有暗示直接依赖关系。 - Martijn Pieters

12

如果你想捷径,跳过关于事件监听器的文档阅读和跳过修改程序使其理解事件的步骤,则:

你可以启动一个 Bash 脚本代替直接启动依赖于 A 的程序 B,该脚本会休眠直到 A 已启动,然后再启动 B。例如,如果你有一个 PostgreSQL 数据库和一个在 PostgreSQL 启动之前不应该启动的服务器:

[program:server]
autorestart=true
command=/.../start-server.sh

[program:postgres]
user=postgres
autorestart=true
command=/usr/lib/postgresql/9.3/bin/postgres ...

然后在 start-server.sh 文件内:

#!/bin/bash

# Wait until PostgreSQL started and listens on port 5432.
while [ -z "`netstat -tln | grep 5432`" ]; do
  echo 'Waiting for PostgreSQL to start ...'
  sleep 1
done
echo 'PostgreSQL started.'

# Start server.
echo 'Starting server...'
/.../really-start-the-server

5
一种解决方案是使用supervisorctl:将程序B的autostart设置为false,在程序A启动的程序中,写入supervisorctl start B
示例: supervisor.cfg文件:
[supervisord]
nodaemon=false
pidfile=/tmp/supervisor.pid
logfile=/logs/supervisor.log

[unix_http_server]
file=/var/run/supervisor.sock

[rpcinterface:supervisor]
supervisor.rpcinterface_factory=supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///var/run/supervisor.sock

[program:A]
command=do_a

[program:B]
command=do_b
autostart=false

do_a程序包含以下内容:

#!/bin/bash
#do things
supervisorctl start B 

说实话,这是@drrzmr建议的解决方案,但我当时并没有理解它。


1
解决方法的问题在于它需要 autorestart=false。对于某些应用程序来说还不错,但对于一些其他应用程序(例如数据库)来说并不太好。 - Charlie Reitzel

3

这个 解决方案对我来说非常好用!

一个解决方法是在进程上设置 autostart=false,然后创建一个引导脚本,其中 autostart=trueautorestart=false(仅一次)。引导程序可以是调用的 shell 脚本 的 supervisorctl start,为每个进程启动。 supervisorctl start 将阻塞,直到进程成功启动。


似乎这很容易成为supervisor.conf中的一个选项。 - Charlie Reitzel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接