作者:finalbsd
Author:FinalBSD
注:有些內容是直接引用相關資料(比如Apache手冊)
從2000年開始,FreeBSD就實現了一個功能”Accept Filters”即接收過濾器。
我們看SOCKET編程的模型。
從這個模型可以看到一旦連接建立,Accpet()會立即返回建立的socket。這樣做有幾個問題:
1、 也許後面根本沒有HTTP請求過來;
2、 請求不完整,屬於非法請求;
這樣,Apache將派生很多的子進程(假設爲prefork模式)去處理這些也許沒有用的(可能是SYN FLOOD)連接,最後進程數滿,Apache不堪重負。
FreeBSD實現的接收過濾器明確的延遲了accpet()的返回,只有當滿足了一定的條件後,比如一個完整的HTTP/1.0或者HTTP /1.1 HEAD或者GET請求完全被FreeBSD內核緩存之後才返回。HEAD和GET之外的其他請求仍然直接有accpet()進程處理。這樣後續的讀寫 socket操作就不需要等待客戶端的請求數據。因此,每個Apache就能處理更多的有效連接。也可以使子進程在accpet()返回後立即處理請求, 因爲這個HTTP請求已經建立而且可以read(),這樣就減少了Apache進程在執行初始的請求解析(解析HTTP請求)前,執行過多的上下文切換 (Context Switch). FreeBSD通過accf_http和accf_data(kldload accf_http)來實現接收過濾,Apache相關配置語法爲AcceptFilter protocol accept_filter,如
AcceptFilter http httpready
AcceptFilter https dataready
httpready接收過濾器(Accept Filter)在內核級別緩衝整個HTTP請求。一旦一個請求體被完整接收,內核將把它發送給服務器。因爲HTTPS請求已經被加密了,所以只使用了 accf_data(9)過濾器。 注:FreeBSD 6.1必須載入這個模塊才能啓動Apache2.2,FreeBSD6.2及後續版本不管是否加載這個模塊都可以啓動Apache,默認不加載,可以在 /etc/rc.conf中加入:apache22_http_accept_enable=”YES”進行啓動時自動加載。
Linux上的默認值是:
AcceptFilter http data
AcceptFilter https data
Linux的TCP_DEFER_ACCEPT並不支持對http請求進行緩衝。除none之外的任何值都將在監聽程序上啓用
TCP_DEFER_ACCEPT 。參見tcp(7)手冊頁以獲得更多詳情。使用none將會爲那個協議禁用接收過濾器(accept
filter)。這對於像nntp這樣需要服務器先發送數據的協議很有用處:
AcceptFilter nttp none
NetScaler似乎也使用了同樣的思想,只將真正的HTTP請求數據發送給後端服務器,而之前的3次TCP握手都由NetScaler本身處理,大大提升了服務器的吞吐量。