【问题标题】:How does a python web server overcomes GILpython web服务器如何克服GIL
【发布时间】:2012-09-26 14:11:53
【问题描述】:

任何网络服务器都可能需要同时处理大量请求。由于python解释器实际上有GIL约束,那么并发是如何实现的?

他们是否使用多个进程并使用 IPC 进行状态共享?

【问题讨论】:

  • 什么状态共享? Web 请求的全部意义在于每个请求都是独立的,没有共享状态。
  • @Daniel Roseman:“会话属性”中的状态(例如在 Java Servlet 应用程序中),即保存在服务器端的信息,通常依靠 HTTP cookie 保存会话 ID 来识别会话请求属于。 Web 浏览器可以在同一个会话中并行提交许多请求。服务器应该有权访问给定会话 ID 的会话属性。

标签: python django concurrency webserver


【解决方案1】:

你通常有很多工人(即 gunicorn),每个工人都被独立的请求分派。其他所有内容(与并发相关)都由数据库处理,因此从您那里抽象出来。

你不需要 IPC,你只需要一个“单一数据源”,它将是 RDBMS、缓存服务器(redis、memcached)等。

【讨论】:

    【解决方案2】:

    首先,请求可以独立处理。但是,服务器希望同时处理它们,以便将每次可以处理的请求数保持在最大值。

    并发这个概念的实现依赖于网络服务器。

    某些实现可能有固定数量的线程或进程来处理请求。如果所有请求都在使用中,则必须等待处理其他请求。

    另一种可能性是为每个请求生成一个进程或线程。为每个请求生成一个进程会导致荒谬的内存和 CPU 开销。产生轻量级线程更好。这样做,您可以每秒为数百个客户提供服务。然而,线程也带来了管理开销,表现在高内存和 CPU 消耗上。

    为了每秒服务数千个客户端,基于异步协程的事件驱动架构是最先进的解决方案。它使服务器能够以高速率为客户端提供服务,而无需产生数以亿计的线程。在Wikipedia page of the so-called C10k problem 上,您可以找到 Web 服务器列表。其中,许多人使用这种架构。

    协程也可用于 Python。看看http://www.gevent.org/。这就是为什么基于例如uWSGI + gevent 的 Python WSGI 应用程序是一个非常高效的解决方案。

    【讨论】:

    • “为每个请求生成一个进程会导致荒谬的内存和 CPU 开销。”这完全取决于操作系统。
    • @IgnacioVazquez-Abrams:对于哪个操作系统来说这是不正确的(“荒谬”是指与线程或协程的开销相比)?
    • 并不是说它不正确,而是“荒谬”的确切定义各不相同;在启动新进程时,Windows 是一大堆热气腾腾的粪便,但 *nice 相比之下要轻得多。
    【解决方案3】:

    正常。 Web 服务主要受 I/O 限制,并且 GIL 在 I/O 操作期间释放。所以要么在没有任何特殊调整的情况下使用线程,要么使用事件循环(例如 Twisted)。

    【讨论】:

    • 我不是在谈论等待/接收请求。我说的是处理它们。例如,如果我收到一个请求,我可能需要做一些处理,比如检查各种 POST 或 GET 请求,这些请求通常写成 python 代码。那么python解释器如何同时执行这些代码块,因为它有GIL约束。
    • 这根本不是真的。并非所有工作负载都受 IO 限制。看到具有最大化 CPU 的 Web 服务器是完全常见的。这取决于正在运行的应用程序。
    猜你喜欢
    • 1970-01-01
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-09
    • 2010-10-24
    • 2019-07-27
    相关资源
    最近更新 更多