如何安全地停止生产程序

时间:2018-01-31 13:18:53

标签: linux python-3.x server rabbitmq continuous-deployment

我们有多台机器正在运行"服务器"。在他们身上,他们有一个程序可以听取不同客户的请求。

在持续部署过程的一部分中,更新服务器程序可能导致未完成的业务被杀死。这是不可取的。我正在寻找一种方法来从一个节点消耗工作,这样我们就可以更新它,而另一个节点负载。

至于一个代表我当前心态的更具体的问题:

你如何发送"信号"所以:

while True and no_signal:
    do_server_work()
如果我们需要升级,

会停止。

对于我们的基础架构,我们有许多客户端向服务器消耗其队列的多个RabbitMQ节点发送请求。

编辑:在linux上,使用python3

1 个答案:

答案 0 :(得分:2)

(我猜你是在Linux上,或者至少在POSIX机器上)

对于编写良好的服务器程序,您应该向他们发送SIGTERM信号(有关详细信息,请参阅signal(7))以轻轻终止它们,并且它们应该明确地(和巧妙地)处理该信号。一种常见的方法是使用kill(1)程序(或基础kill(2)系统调用)。

编写糟糕的服务器程序可能无法正常处理SIGTERM。然后(几秒钟后)你可能需要用SIGKILL杀死它们,但这可能会使它们(或它们的文件)处于某种不一致的状态,因为SIGKILL无法被捕获。

记录某些服务器程序的行为不同。例如,他们可能会使用其他inter-process communication设施来轻轻终止。

正确处理SIGTERM是一种广泛使用的约定(如果您正在编写处理它的服务器,请同时阅读signal-safety(7))。有些服务器可能有不同的服务器。

顺便说一下,在C级编写安全信号处理程序(仔细阅读signal-safety(7))有几种技巧。一种是使用由信号处理程序设置的全局volatile sig_atomic_t变量,并在代码中定期测试 (可能在您的event loops中)。另一个是设置(在初始化时,使用pipe(2)pipe(7)来自我,让你的信号处理程序write(2)一个或几个字节(这是合法的,因为{{ 3}}是一个异步信号安全函数)和事件循环中管道的write(2)poll(2)。后来的技巧很常见,在Qt中是read(2)

Python可能使用第一个技巧或类似的东西(可能与其臭名昭着的documented相关)来处理signals。由于它是GIL,你可以研究它的源代码(现在,我太懒了)。