2012-09-26 62 views
11

任何web服務器可能需要同時處理很多請求。由於python解釋器實際上具有GIL約束,因此如何實現併發?python web服務器如何克服GIL

他們是否使用多個進程並使用IPC進行狀態共享?

+4

什麼狀態共享? Web請求的要點是每個都是獨立的,沒有共享狀態。 –

回答

2

正常。 Web服務主要是I/O綁定的,並且在I/O操作期間釋放GIL。所以無論使用什麼線程都沒有特殊的設置,或者使用事件循環(如Twisted)。

+1

我不是在談論等待/接收請求。我正在談論處理它們。例如,如果我收到一個請求,我可能需要做一些處理,比如檢查各種POST或GET請求,這些請求通常寫成python代碼。那麼Python解釋器如何同時執行這些代碼塊,因爲它具有GIL約束。 –

+2

這簡直是不真實的。並非所有工作負載都是IO綁定的。查看具有最大CPU的Web服務器是完全常見的。這取決於正在運行的應用程序。 – usr

1

你通常會有很多工人(即gunicorn),每個工人都被派出獨立的請求。其他所有內容(併發相關)都由數據庫處理,因此它是從您的數據庫中抽象出來的。

你不需要IPC,你只需要一個「單一數據源」,這將是RDBMS,緩存服務器(Redis的,memcached的),等等。

1

首先,請求可以是獨立處理。但是,服務器同時想要處理它們以便保持每次最多可處理的請求數。

併發這個概念的實現取決於網絡服務器。

某些實現可能具有固定數量的線程或進程來處理請求。如果全部正在使用中,其他請求必須等待處理。

另一種可能性是爲每個請求生成一個進程或線程。爲每個請求產生一個進程會導致荒謬的內存和CPU開銷。產生輕量級線程更好。這樣做,您可以每秒爲數百個客戶端提供服務。但是,線程也會帶來管理開銷,體現在高內存和CPU消耗上。

對於每秒服務數千個客戶端,基於異步協程的事件驅動架構是最先進的解決方案。它使服務器能夠以高速率爲客戶提供服務,而不會產生大量的線程。在Wikipedia page of the so-called C10k problem上,您可以找到一個Web服務器列表。其中許多人使用這種架構。

協程也適用於Python。請看http://www.gevent.org/。這就是爲什麼基於例如uWSGI + gevent的Python WSGI應用程序是一個非常高性能的解決方案。

+0

「爲每個請求產生一個進程導致荒謬的內存和CPU開銷。」這完全取決於操作系統。 –

+0

@ IgnacioVazquez-Abrams:對於哪種操作系統來說這是不正確的(「荒謬」是指與線程或協程的開銷相比)? –

+0

這並非並非如此,而是「荒謬」的確切定義各不相同;在開始新工藝時,Windows是一大堆有福的排泄物,但相比之下,* nices往往要輕得多。 –