如何将 SIGUSR1 处理程序添加到 Twisted 程序中?
How to add a SIGUSR1 handler to a Twisted program?
我正在寻找一种方法来检查基于 Twisted 的程序的状态,这样我就可以确定连接的客户端数量并查看我收集的其他指标(例如连接建立时间或最后一次联系的时间)。
我的想法是为 SIGUSR1
添加一个信号处理程序到进程中,这样当进程接收到它时,它会将状态转储到已知位置的文件中。这有几个问题:
- Twisted 用它自己的处理程序覆盖信号处理程序,因为当信号到达时,进程在
stdout
上以 "user signal 1 received" 结束并且我的代码没有被调用
- 考古研究 on a mailing list 表明 Twisted 不会覆盖
SIGINT
的处理程序;然而情况并非如此(Python 2.7.11 和 Twisted 16.1.1),进程在 stdout
. 上以 "KeyboardInterrupt" 退出
- 其他资源建议
reactor.run(installSignalHandlers=False)
或 reactor.run(installSignalHandlers=0)
,但这似乎没有效果。
因此我有几个问题:
- 在意识形态上正确的信号处理方式是什么? (如果可能的话)
- 为 Twisted 服务器实施此类 "state introspection" 设施的推荐方法是什么? (我正在考虑让它在另一个端口上监听 TCP 连接,并将其用作 POSIX 信号的替代方案 - 但我觉得我让事情变得太复杂了)。
感谢您花时间阅读本文,我期待着来自这个星球的蜂巢思维的提示。
这是邮件列表的相关摘录:
> If you do this, you'll break spawnProcess. Fortunately, if you just
> install a SIGINT handler, Twisted won't stomp on it:
> exarkun at charm:~$ python
> Python 2.5.2 (r252:60911, Jul 31 2008, 17:28:52) [GCC 4.2.3
> (Ubuntu 4.2.3-2ubuntu7)] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
> >>> def f(*a):
> ... print 'sigint'
> ... >>> import signal
> >>> signal.signal(signal.SIGINT, f)
>
> >>> from twisted.internet import reactor
> >>> reactor.run()
> sigint
> sigint
> sigint
> Quit
从 Twisted 17.1 开始,只有 twistd
安装 SIGUSR1
处理程序,如果您已经为该信号安装了处理程序,它将跳过安装。
当您将 SIGUSR1 发送到您的进程时,您在 stdout 上看到的消息:
user signal 1 received
是OS默认系统处理程序。该默认行为是退出进程。这表明您和 Twisted 都没有为 SIGUSR1
安装处理程序。当您认为它是 运行 并且您没有使用 twistd.
时,您的处理程序安装代码似乎很可能只是没有得到 运行
然而...
what is the ideologically correct way to handle signals? (if it is possible at all)
很有可能根本不可能。信号是一个兔子洞。如果您在这件事上有任何选择,请远离他们。将异步信号传递引入任何 Python 程序都是令人担忧的。它可能在某些情况下可以正确可靠地完成,但我不会打赌。由于 POSIX 的缺点和额外的复杂性 Python,信号与多线程的交互很复杂。信号处理程序是一种共享的全局资源(正如您所指出的),因此尝试使用它们的不同代码库之间存在复杂的交互。
最后,您可以使用多种替代方法来解决这些问题。
what is the recommended way to implement such "state introspection" facilities for Twisted servers? (I was thinking of making it listen for TCP connections on another port, and use that as an alternative for a POSIX signal - but I feel that I am making things too complicated).
使用 POSIX 信号以外的机制可能看起来更复杂,但我建议它更简单,尽管它可能需要稍微多一些输入。
我没有针对 "state introspection" 的 一般 提案,但这里有一个针对这种情况的具体提案:向您的流程添加一个 HTTP 服务器。
举个简单的例子:
from json import dumps
from twisted.web.server import Site
from twisted.web.resource import Resource
from twisted.internet.endpoints import serverFromString
class StateResource(Resource):
def render(self, request):
return dumps({"your": "state info"})
root = Resource()
root.putChild(b"", StateResource())
serverFromString("tcp:12345").listen(Site(root))
是的,它比等效的基于信号的代码长 10 行。但是,它没有奇怪的多线程或多进程交互。它与平台无关。它不会践踏共享资源(也不会被践踏)——除了我随机选择的那个 tcp 端口(如果你不喜欢那个,你可以 运行 它通过 UNIX 套接字代替 -如果这对您很重要,还可以授予访问控制权)。
这个 真正 开始成为明显更好的解决方案的地方是当您想要向您的应用程序添加健康检查以便您的主管可以监控它时。然后您想要添加一个指标报告器,以便您的监控系统可以提取该数据并将其呈现给您的 SRE 或运营团队。等等。可以处理这些附加功能的基于信号的解决方案变得更加复杂,我怀疑最终的 SLOC 总数高于 HTTP 解决方案。即,HTTP 服务器可以很好地适应新的功能需求。基于信号的解决方案不会。
我正在寻找一种方法来检查基于 Twisted 的程序的状态,这样我就可以确定连接的客户端数量并查看我收集的其他指标(例如连接建立时间或最后一次联系的时间)。
我的想法是为 SIGUSR1
添加一个信号处理程序到进程中,这样当进程接收到它时,它会将状态转储到已知位置的文件中。这有几个问题:
- Twisted 用它自己的处理程序覆盖信号处理程序,因为当信号到达时,进程在
stdout
上以 "user signal 1 received" 结束并且我的代码没有被调用 - 考古研究 on a mailing list 表明 Twisted 不会覆盖
SIGINT
的处理程序;然而情况并非如此(Python 2.7.11 和 Twisted 16.1.1),进程在stdout
. 上以 "KeyboardInterrupt" 退出
- 其他资源建议
reactor.run(installSignalHandlers=False)
或reactor.run(installSignalHandlers=0)
,但这似乎没有效果。
因此我有几个问题:
- 在意识形态上正确的信号处理方式是什么? (如果可能的话)
- 为 Twisted 服务器实施此类 "state introspection" 设施的推荐方法是什么? (我正在考虑让它在另一个端口上监听 TCP 连接,并将其用作 POSIX 信号的替代方案 - 但我觉得我让事情变得太复杂了)。
感谢您花时间阅读本文,我期待着来自这个星球的蜂巢思维的提示。
这是邮件列表的相关摘录:
> If you do this, you'll break spawnProcess. Fortunately, if you just > install a SIGINT handler, Twisted won't stomp on it: > exarkun at charm:~$ python > Python 2.5.2 (r252:60911, Jul 31 2008, 17:28:52) [GCC 4.2.3 > (Ubuntu 4.2.3-2ubuntu7)] on linux2 > Type "help", "copyright", "credits" or "license" for more information. > >>> def f(*a): > ... print 'sigint' > ... >>> import signal > >>> signal.signal(signal.SIGINT, f) > > >>> from twisted.internet import reactor > >>> reactor.run() > sigint > sigint > sigint > Quit
从 Twisted 17.1 开始,只有 twistd
安装 SIGUSR1
处理程序,如果您已经为该信号安装了处理程序,它将跳过安装。
当您将 SIGUSR1 发送到您的进程时,您在 stdout 上看到的消息:
user signal 1 received
是OS默认系统处理程序。该默认行为是退出进程。这表明您和 Twisted 都没有为 SIGUSR1
安装处理程序。当您认为它是 运行 并且您没有使用 twistd.
然而...
what is the ideologically correct way to handle signals? (if it is possible at all)
很有可能根本不可能。信号是一个兔子洞。如果您在这件事上有任何选择,请远离他们。将异步信号传递引入任何 Python 程序都是令人担忧的。它可能在某些情况下可以正确可靠地完成,但我不会打赌。由于 POSIX 的缺点和额外的复杂性 Python,信号与多线程的交互很复杂。信号处理程序是一种共享的全局资源(正如您所指出的),因此尝试使用它们的不同代码库之间存在复杂的交互。
最后,您可以使用多种替代方法来解决这些问题。
what is the recommended way to implement such "state introspection" facilities for Twisted servers? (I was thinking of making it listen for TCP connections on another port, and use that as an alternative for a POSIX signal - but I feel that I am making things too complicated).
使用 POSIX 信号以外的机制可能看起来更复杂,但我建议它更简单,尽管它可能需要稍微多一些输入。
我没有针对 "state introspection" 的 一般 提案,但这里有一个针对这种情况的具体提案:向您的流程添加一个 HTTP 服务器。
举个简单的例子:
from json import dumps
from twisted.web.server import Site
from twisted.web.resource import Resource
from twisted.internet.endpoints import serverFromString
class StateResource(Resource):
def render(self, request):
return dumps({"your": "state info"})
root = Resource()
root.putChild(b"", StateResource())
serverFromString("tcp:12345").listen(Site(root))
是的,它比等效的基于信号的代码长 10 行。但是,它没有奇怪的多线程或多进程交互。它与平台无关。它不会践踏共享资源(也不会被践踏)——除了我随机选择的那个 tcp 端口(如果你不喜欢那个,你可以 运行 它通过 UNIX 套接字代替 -如果这对您很重要,还可以授予访问控制权)。
这个 真正 开始成为明显更好的解决方案的地方是当您想要向您的应用程序添加健康检查以便您的主管可以监控它时。然后您想要添加一个指标报告器,以便您的监控系统可以提取该数据并将其呈现给您的 SRE 或运营团队。等等。可以处理这些附加功能的基于信号的解决方案变得更加复杂,我怀疑最终的 SLOC 总数高于 HTTP 解决方案。即,HTTP 服务器可以很好地适应新的功能需求。基于信号的解决方案不会。