python - 如何在 Python 中仅在程序退出临界区后处理 SIGTERM?

标签 python linux multithreading python-2.7 signals

一个名为“eventcollector”的 Python 2.7 程序连续运行并轮询网络服务以获取事件。然后它将每个事件作为 JSON 对象附加到文件的末尾 -/var/log/eventsexample.json。代理跟踪文件并将事件发送到基于云的软件“anycloud”来处理事件。

我需要使 eventcollector 成为一个行为良好的 UNIX 守护进程,然后使该守护进程成为 systemd 中的一项服务。我将为此目的创建的 systemd .service 单元将让 systemd 知道在停止此服务时,它必须在发送 SIGTERM 之后等待 15 秒,然后再发送 SIGKILL。这将使 eventcollector 有时间保存状态并关闭它正在写入的文件(它自己的日志文件和事件文件)。 awill 配置为我现在必须让这个程序更有弹性。程序必须能够保存其状态,以便在终止和重新启动时,程序知道它在何处停止。

Eventcollector 对任何云都没有可见性。它只能看到源服务中的事件。如果 Eventcollector 由于重启而死,它必须可靠地知道它的新 start_time 是什么来查询事件的源服务。因此,在退出和保存状态之前完成将事件写入文件的关键业务是至关重要的。

我的问题具体是关于如何处理 SIGTERM,以便程序有时间完成它正在做的事情,然后保存它的状态。

然而,我担心的是,除非我在每条消息写入文件后写入状态(这会消耗比看起来需要的更多的资源),否则我无法确定我的程序不会在不及时保存状态的情况下终止。这样做的影响是重复的消息,而重复的消息是 Not Acceptable 。

如果我必须承受性能损失,我会的,但我更愿意有一种方法来优雅地处理 SIGTERM,以便程序可以巧妙地执行以下操作(简化的伪代码摘录):

while true:
    response = query the webservice using method returning 
               a list of 100 dictionaries (events)
    for i in response.data:
        event = json.dumps(i)
        outputfile.write(i)  #<  Receive SIGTERM during 2nd event, but do not 
                                  exit until the for loop is done.  (how?)


signal handler:
    pickle an object with the current state.

想法是,即使在写入第 2 个事件时收到 SIGTERM,程序也会等到它写入第 100 个事件后才决定可以安全地处理 SIGTERM。

我读入了https://docs.python.org/2/library/signal.html :

There is no way to “block” signals temporarily from critical sections (since this is not supported by all Unix flavors).

我的一个想法似乎太复杂了,在我看来必须有更简单的方法。想法是:

  1. 主线程有一个信号处理程序负责处理 SIGTERM。
  2. 主线程可以通过一种新颖的协议(protocol)与工作线程通信,以便工作线程在进入临界区时通知主线程。
  3. 当主线程收到 SIGTERM 时,它会一直等待,直到工作线程告诉主线程它已超出临界区。然后主线程告诉它保存状态并关闭。
  4. 当工作线程结束时,它告诉主线程它完成了。然后主线程干净地退出并返回零状态。

补充

我正在考虑使用 python-daemon据我所知,这是 Ben Finney 对他写的 PEP 的引用实现 [PEP 3143]( https://www.python.org/dev/peps/pep-3143/ >。我理解基于他所写的内容以及我从 UNIX 和 UNIXlike 操作系统的经验中所看到的内容守护进程的“良好行为”尚未达成一致。我提到这一点是因为,我同意 PEP 3143,并希望实现这一点,但是它没有回答我当前关于如何处理信号的问题,因为我想做。

最佳答案

你的守护进程是 python 2.7
并且 python 在进行系统调用时使用起来不太方便,对 /dev/shmsemaphores
不利 我不确定在 python 中使用 global variables 的副作用和注意事项
文件锁 很脆弱,文件系统 IO 对信号处理程序不利
所以我没有完美的答案,只有想法。

这是我在用 C 实现一个小守护进程时的想法

  1. 主线程设置同步点,对于C程序,/dev/shm,信号量,全局变量,文件锁是我考虑过的东西,最后我选择了/dev/shm
  2. 设置信号处理程序,在接收到 SIGTERM 时,通过更改存储在/dev/shm 中的值来提升同步标志
  3. 在每个工作线程中,在作业的一部分之后检查/dev/shm 的同步标志,如果出现标志则退出
  4. 在主线程中,设置一个收集线程,尝试收集所有其他工作线程,如果收集成功,则继续退出守护程序本身。

关于python - 如何在 Python 中仅在程序退出临界区后处理 SIGTERM?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57781922/

相关文章:

python - 如何使用户按下按钮后,他们可以在 Tkinter for python 3.7 中输入信息

Python Pandas 根据条件添加列值

python - 如何在 GCP 计算引擎上从 PyCharm 运行 python 脚本?

linux - 找不到包 'libxml-2.0'

node.js - cluster.fork() 是否保证使用不同的 CPU 内核?

python - 如何使用aiocoap库观察CoAP资源?

linux - 在 Ubuntu : I can not change files and get "file can not be found" even though the file exists?

python - python 中的交互式 shell 程序包装

c++ - 奇怪的 boost::this_thread::sleep 行为

multithreading - CUDA统一内存可以被另一个CPU线程写入吗?