從2.2x開始,Apache使用了Event模式,在 Linux,使用Epoll+TCP 延遲觸發事件的方式來提高伺服器的高並發串連下的效能. Event模式是在原有的Worker模式基礎上改進,因此Event模式的參數與Worker模式基本一致.
每個進程啟動一個單獨的處理網路事件的線程,叫做listener_thread;
他負責監控listen_fd和其他所有的已經建立串連的fd的事件,使用epoll監孔網路事件
當檢測到listen_fd有讀事件(client必須有資料發送)發生時,首先調用accept函數建立串連,然後觸發背景工作執行緒去處理網路事件(一般情況下會執行HTTP請求)
背景工作執行緒平時是使用ap_queue隊列處於等待狀態的,由listen_thread線程觸發(使用ap_queue_push觸發),背景工作執行緒被啟用後,調用process_socket處理socket事件,若是資料讀事件,則讀取請求資料,
apache2.2.9對串連做了特殊處理,只在有資料發送的時候才開始建立串連,串連請求才會觸發背景工作執行緒,即使用了TCP的一個選項,叫做延遲接受串連TCP_DEFER_ACCEPT,加了這個選項後,若用戶端只進行TCP串連,不發送請求,則不會觸發Accept操作,也就不會觸發背景工作執行緒去幹活,進行了簡單的防攻擊(TCP串連)。可以使用Telnet進行測實驗證:
主機10.2.224.63為用戶端機器;10.2.226.7為apache伺服器機器
telnet 10.2.226.7 80
然後在10.2.224.63用戶端機器上使用netstat查看,發現串連已經建立,處於ESTABLISHED狀態
然後再到apache伺服器上使用netstat查看,發現是處於SYN_RECV狀態。
雖然該模式解決了KeepAlive問題,即串連數過多問題,但還是有點缺陷,就是若有人故意緩慢發送請求給Apache,還是會佔用背景工作執行緒,因為當有串連上網路事件發送後,會交給一個單獨的線程處理請求,若請求緩慢發送的話,背景工作執行緒就一直被佔用了.
另外Apache2.2.9版本引入了一條指定線程堆棧的指令 ThreadStackSize , 該指令可以指定背景工作執行緒的堆棧,避免線程過多而耗盡記憶體.