我正在研究一些基於Apache的MPM prefork服務器的Python代碼。我更像是一個應用程序員,而不是網絡程序員,從我讀史蒂文斯已經有10年了,所以我正在努力加快理解代碼。accept()與在多個進程之間共享的套接字(基於Apache預執行)
我發現了how Apache's prefork code works, by Sander Temme的簡短說明。
通常以root身份運行的父進程綁定到套接字 (通常是端口80或443)。它產生子代,繼承套接字的開放 文件描述符,並將uid和gid更改爲非特權用戶和組。孩子們構造了監聽器文件描述符(如果有多個監聽器) 的輪詢集 並監視其上的活動。如果找到活動,孩子在活動套接字上調用 accept()並處理連接。當它與 完成時,它返回到觀看pollset(或聽衆文件 描述符)。
由於多個子項都處於活動狀態,並且它們都繼承了相同的套接字文件描述符,所以它們將觀察同一個pollset。 一個接受互斥體只允許一個孩子實際觀看民意調查組, ,一旦發現一個活動的套接字,它將解鎖互斥體,所以 下一個孩子可以開始觀看民意調查組。如果只有一個 偵聽器,則不會使用接受互斥量,並且所有子級都將在 accept()中掛起。
這幾乎是我看到的代碼的工作方式,但我不明白一些事情。
1)「孩子」和「聽衆」之間有什麼區別?我認爲每個孩子都是一個聽衆,這對我所看到的代碼來說是真實的,但在Temme的描述中,可以有「單一的聽衆」和「孩子」。孩子什麼時候會有多個聽衆?
2)(與1相關)這是每進程互斥鎖還是系統互斥鎖?對於這個問題,爲什麼有一個互斥體?不接受(2)對所有聽衆都做自己的互斥嗎?我的研究表明,我確實需要一個互斥體,並且互斥體必須貫穿整個系統。 (羊羣,旗語等)
Temme接着說:在共享內存 區(記分牌)
兒童紀錄,當他們最後 服務的請求。空閒的孩子可能會被 父母程序殺死,致 滿足MaxSpareServers。如果太少, 孩子空閒,父母會 產卵孩子滿足 MinSpareServers。
3)是否有一個很好的參考代碼(最好在Python中)?我發現Perl的Net::Server::Prefork,它使用管道而不是共享內存作爲記分板。我發現了一篇Randal Schwartz的文章,它只執行preforking,但沒有記分牌。
pre-fork example from the Perl Cookbook沒有任何類型的鎖定選擇,Chris Siebenmann's Python example表示它基於Apache,但爲記分板使用配對套接字,而不是共享內存,並使用套接字控件,將給定子控件包含到'接受。這完全不符合Apache描述。
你是否使用'mod_wsgi'作爲Apache和Python之間的接口?如果是這樣,它應該爲你處理所有這些。 – 2009-08-18 13:04:02
這是一個純Python預執行WSGI服務器。我的客戶希望爲不需要Apache和mod_wsgi的地方提供輕量級解決方案,或者同等的解決方案。我找到的唯一一個只有Python的WSGI服務器是Spawning,它需要eventlet。 ......雖然現在我發現flup有一個像Siebenmann's的實現,它使用記分板的管道而不是共享內存,並且具有可接受的許可證給我的客戶端。 – 2009-08-18 13:23:13