HTTP請求過濾器FreeBSD accf_http)

 

作者:finalbsd

Author:FinalBSD
注:有些內容是直接引用相關資料(比如Apache手冊)
從2000年開始,FreeBSD就實現了一個功能”Accept Filters”即接收過濾器。

我們看SOCKET編程的模型。

socket3.jpg

  
從這個模型可以看到一旦連接建立,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本身處理,大大提升了服務器的吞吐量。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章