1

我正在尝试设计一个弹性且高度可用的 python API 后端服务。核心服务旨在持续运行。该服务必须为我的每个租户独立运行。这是必需的,因为核心服务是一个阻塞服务,每个租户的执行需要独立于任何其他租户的服务。

核心服务将由供应服务启动。供应商也是一个持续运行的服务,负责做家务功能,即在租户注册时启动核心服务,检查所需的环境和属性以及停止核心服务等。

目前我正在使用该multiprocessing模块从供应商服务中生成核心服务的子实例。为每个租户使用一个线程的多线程服务也是一种选择,但如果任何线程崩溃,则会中断其他租户的服务。理想情况下,我希望所有这些都作为后台进程运行。问题是

  1. 如果我守护供应商服务,multiprocessing将不会让该守护程序创建子进程。这是写在这里

  2. 如果provisioner服务死了,那么所有的孩子都将成为孤儿。我该如何从这种情况中恢复过来。

显然,我对不遵循这种multiprocessing使用模式的解决方案持开放态度。

4

2 回答 2

2

我建议你采取不同的方法。使用发行版中可用的系统工具来管理进程的生命周期,而不是自己生成它们。预配器也会简单得多,因为它不必重现您的操作系统可以轻松完成的工作。

在 Ubuntu/CentOS 6 系统上,您可以使用 Upstart,它与旧的 sysvinit 相比具有很多优势(激进的并行化、重生、简单的 init 配置语法等)。

还有 SystemD,它在设计上类似于 upstart,在 OpenSuse 中是默认的。

然后,provisioner 只能用于为每个服务创建所需的 init 配置,并使用 subprocess 模块启动或停止它们。然后,您可以监控您的实例,以防 upstart 无法重新生成实例,并发送警报,或尝试再次启动服务。

使用这种方法,您可以将用户服务的所有实例彼此隔离。如果供应商崩溃,其余服务将保持运行。

例如,假设您的供应商正在后台运行。它通过 AMQP 或其他方式获取消息以创建用户并为该用户启动服务。一种可能的流程是:

  1. 创建用户
  2. 为新用户做任何需要的引导
  3. 创建 /etc/init/[用户名]_service.conf
  4. 启动 [用户名]_service

初始化脚本可能类似于:

description "start Service for [username]"

start on runlevel [2345]
stop on runlevel [!2345]

respawn

# Run before process
pre-start script
end script

exec /bin/su -c "/path/to/your/app" <username>

通过这种方式,您可以将进程管理从您的配置程序卸载到系统新贵守护程序。您只需要以简单的方式进行作业管理(在创建或删除用户时创建/销毁服务)。

于 2013-07-29T08:58:09.200 回答
0

在类似 debian 的情况下,您可以使用

start-stop-daemon --start --quiet --background --make-pidfile --pidfile $PIDFILE --exec $DAEMON --chuid $USER --chdir $DIR -- \
    $DAEMON_ARGS 

孩子们必须在完成任务后死亡。父进程必须如此简单如此可行,仅在主循环中“重新筛选任务 - 生成子进程”。

于 2013-07-29T08:41:52.297 回答