假设我们有这样一个系统:
______
{ application instances ---network--- (______)
{ application instances ---network--- | |
requests ---> load balancer { application instances ---network--- | data |
{ application instances ---network--- | base |
{ application instances ---network--- \______/
请求进入,负载均衡器将其发送到应用程序服务器实例,并且应用程序服务器实例与数据库(LAN上的其他位置)通信。应用程序实例可以是单独的进程或单独的线程。为了涵盖所有基础,假设有几个相同的进程,每个进程都有一组相同的应用程序服务线程。
如果数据库运行缓慢,或者网络陷入困境,请求服务的吞吐量显然会变得更糟。
现在,在我的所有Python前体验中,这将伴随着应用程序实例在CPU使用中的相应 drop - 他们将花费更多时间阻止I / O和花在CPU密集型事情上的时间减少了。
然而,我被告知使用Python,情况并非如此 - 在某些Python情况下,这种情况会导致Python的CPU使用率 up ,也许一直到100 %。关于全局解释器锁和多线程的事情可能导致Python花费所有时间在线程之间切换,检查它们中是否有任何来自数据库的答案。 “因此,最近单流程事件驱动的库增加了。”
这是对的吗?当他们的I / O延迟增加时,Python应用程序服务线程是否实际使用 more CPU?
答案 0 :(得分:6)
理论上,在实践中,没有可能;这取决于你在做什么。
有一个完整的hour-long video和pdf about it,但实际上它归结为GIL的一些无法预料的后果,CPU与IO绑定线程与多核。基本上,等待IO的线程需要唤醒,因此Python开始“抢先”其他线程每个Python“滴答”(而不是每100个滴答)。然后,IO线程无法从CPU线程中获取GIL,导致循环重复。
这太过于简单了,但这就是它的要点。视频和幻灯片包含更多信息。它在多核机器上表现出来并且是一个更大的问题。如果进程从os接收到信号(因为它也触发了线程切换代码),也可能发生这种情况。
当然,正如其他海报所说,如果每个海报都有自己的过程,那就会消失。
巧合的是,幻灯片和视频解释了为什么有时候你不能在Python中使用CTRL + C.
答案 1 :(得分:1)
关键是在不同的进程中启动应用程序实例。否则,似乎可能会出现多线程问题。
答案 2 :(得分:1)
不是不是这样。停止传播FUD。
如果您的python应用程序在C API调用上被阻止。阻塞套接字或文件读取,它可能释放了GIL。
答案 3 :(得分:1)
关于全局解释器锁和多线程的一些东西可能导致Python花费所有时间在线程之间切换,检查它们中是否还有来自数据库的答案。
这完全没有根据。如果所有线程都在I / O上被阻塞,那么Python应该使用0%的CPU。如果有一个未阻塞的线程,它将能够在没有GIL争用的情况下运行;它将定期释放并重新获取GIL,但它不会在其他线程上“检查”任何工作。
但是,在多核系统中,如果存在CPU绑定线程,则线程必须等待一段时间才能重新获取GIL,以及响应时间是否下降(详情请参阅this presentation)。但这对大多数服务器来说应该不是问题。