关于Python中的GIL

9
我知道GIL(全局解释器锁)会阻止Python在多个核心上运行其线程。如果是这样的话,为什么像Youtube和Instagram这样的公司还在使用Python作为其Web服务器的语言呢?
PS:我知道有一些替代方案,例如multiprocessing可以解决此问题。但如果有人能提供他们处理过的情况,那就太好了。
3个回答

5

Python经常被用于处理服务器端,在Web服务器中使用,但通常不作为Web服务器。

在普通的设置中:我们有Apache或其他Web服务器来处理大量的进程(服务器端)(Python通常使用WSGI)。请注意通常Apache直接处理“静态”文件。因此我们有一个Apache服务器,许多并行的Apache进程(用于处理连接和基本HTTP),以及许多Python进程,每次处理一个连接。

这些进程中的每一个都是独立的(它们只使用相同的资源),因此您可以轻松地编写服务器端部分,而无需担心死锁。这主要是一个权衡:代码性能和轻松快速地生成代码而不会出现巨大问题。但通常具有Python的Web服务器也很好扩展(甚至对于大型站点),而服务器比程序员更便宜。

请注意:通过仅在一个进程中具有一个请求也可以增加安全性。


2
虽然有点晚,但我会尝试给出一般而有用的答案。 @Giacomo Catenazzi 的回答很好,但部分内容事实上是错误的。 API请求(或其他形式的Web请求)是从已经运行的进程中服务的。这个“已经运行”的进程的创建由像gunicorn这样的Web服务器处理,它在启动时创建指定数量的进程,这些进程不断地运行您的Web应用程序中的代码,等待服务于任何传入的请求。 不用说,每个进程都受到GIL的限制,只能一次运行一个线程。但是,在其生命周期内,一个进程处理多个(通常是许多)请求。在这里,如果我们能够理解请求的流程,那就更好了。
我们将以Flask为例,但这适用于大多数Web框架。当请求来自Nginx时,它会被交给Gunicorn,后者通过WSGI与您的Web应用程序进行交互。当请求到达框架时,将创建一个应用上下文并将一些变量推入应用上下文中。然后它遵循大多数人熟悉的常规路线:路由、数据库调用、响应创建等。然后,响应再次通过WSGI交回给Gunicorn。在交接响应的同时,应用上下文被拆除。因此,每个新请求创建的是应用上下文而不是进程。
另外,我只谈到了Gunicorn中的同步工作进程,但它还有异步工作进程的选项,可以通过协程并行处理多个请求。但那是一个单独的话题。
所以回答你的问题:
  1. Nginx(能够同时处理多个请求)
  2. Gunicorn在启动时创建n个进程池,并在管理该池方面进行管理,如果进程退出或被卡住,它会杀死/重新创建并将其添加到池中。
  3. 每个进程一次只处理1个请求。

了解更多关于gunicorn的设计以及如何使用它来帮助您实现需求。这篇文章是关于gunicorn与flask的理解很好的线索。而这个资源则是了解flask应用上下文的绝佳来源。


每个进程一次只能处理一个请求。当启动应用程序时,如果设置了threading=True会发生什么? - Venkataramana

1

GIL存在于CPython中(使用C语言编写的Python解释器,使用最广泛),其他解释器版本如JythonIronPython没有这样的问题,因为它们没有GIL。

即使使用CPython,您仍然可以进行并发操作,只需在C中完成您的任务,然后在Python代码中“链接”它,就像Numpy或类似工具一样。

另一个问题是,即使您的页面使用Flask或Django,当您在生产服务器上设置时,您会有Apache或Nginx等真正的负载均衡器,它可以同时为许多人提供页面服务。

参考Flask文档(链接)

Flask内置的服务器不适合生产环境,因为它无法很好地进行扩展,并且默认情况下一次只能处理一个请求。 [...]

如果您想将Flask应用程序部署到此处未列出的WSGI服务器,请查询服务器文档以了解如何在其中使用WSGI应用程序。请记住,您的Flask应用程序对象是实际的WSGI应用程序。


是的,Apache可以使用,但如何利用系统中可用的核心呢?您在生产中是否使用了多处理或其他模式? - Arunagiriswaran Ezhilan
你的意思是在你的.py应用程序内部吗?在这种情况下(我从未尝试过,但是...),使用与CPython不同的其他解释器或者将其部分编码为C。 :/ - Daniel Rodríguez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接