我正在尝试设计一个有弹性且高度可用的 python API 后端服务。核心服务旨在持续运行。该服务必须为我的每个租户独立运行。这是必需的,因为核心服务是阻塞服务,每个租户的执行需要独立于任何其他租户的服务。
核心服务将由供应服务启动。供应商也是一个持续运行的服务,负责执行内务管理功能,即在租户注册时启动核心服务,检查所需的环境和属性并停止核心服务等。
目前,我正在使用 multiprocessing
模块从配置服务生成核心服务的子实例。为每个租户提供一个线程的多线程服务也是一种选择,但如果任何线程崩溃,它的缺点是会中断其他租户的服务。理想情况下,我希望所有这些都作为后台进程运行。问题是
如果我守护提供者服务,
multiprocessing
将不会让该守护进程创建子进程。这是写here如果供应商服务终止,那么所有的 child 都将成为孤儿。我该如何从这种情况中恢复过来。
显然,我对不遵循此 multiprocessing
使用模型的解决方案持开放态度。
最佳答案
我建议您采用不同的方法。使用发行版中可用的系统工具来管理进程的生命周期,而不是自己生成它们。配置器也会简单得多,因为它不必重现您的操作系统可以毫不费力地做的事情。
在 Ubuntu/CentOS 6 系统上,您可以使用 Upstart,它与旧的 sysvinit 相比有很多优势(积极的并行化、重生、简单的初始化配置语法等)。
还有 SystemD,在设计上类似于 upstart,并且在 OpenSuse 中是默认的。
配置器然后只能用于为每个服务创建所需的初始化配置,并使用子进程模块启动或停止它们。然后,您可以监控您的实例,以防 upstart 无法重生实例,并发送警报,或尝试再次启动服务。
使用这种方法,您可以将所有用户服务实例相互隔离。如果供应商崩溃,其余服务将保持正常。
例如,假设您的供应商在后台运行。它通过 AMQP 或其他方式获取消息以创建用户并为该用户启动服务。一种可能的流程是:
- 创建用户
- 为新用户做任何必要的引导
- 创建/etc/init/[用户名]_service.conf
- 启动[用户名]_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>
通过这种方式,您可以将进程管理从供应商卸载到系统 Upstart 守护进程。您只需要通过简单的方式进行作业管理(在创建或删除用户时创建/销毁服务)。
关于python - 如何在 python 中设计弹性和高可用的服务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17918594/