眾所周知,Nginx是當下最流行的Web伺服器,它具有很強的負載均衡,反向代理,郵件代理以及靜態快取的功能。在提供這些功能的同時,Nginx的效能也極其優秀,可以輕鬆支援百萬、千萬級的併發連線,能夠為Tomcat、Django等效能不佳的Web應用抗住絕大部分外部流量。那麼,Nginx是如何實現高速併發處理呢?這就要從它優秀的架構設計來說起。
框架結構
如下圖所示,Nginx結合採用多程序和IO多路複用的結構處理併發客戶請求。
Master程序主要負責訊號處理,監控和管理Worker程序。 Master程序本身不處理具體業務。Worker程序處理具體業務,包括處理連線請求和網路讀寫事件的處理。多個worker程序可以獨立地處理各自的客戶連線。Worker程序之間透過訊號量和共享記憶體進行通訊。
透過配置與系統CPU等量的worker程序,可以實現某一個程序繫結某一個特定CPU從而減少系統開銷。在每一個worker程序處理多個client併發連線請求時,Nginx 採用IO多路複用技術在一個程序內同時處理多個client的網路讀寫事件。與多程序/執行緒處理多連線請求模型相比,IO多路複用可以減少大量的程序排程帶來的系統開銷,從而提高系統整體的處理效能。
併發處理方式
網路伺服器在處理併發處理方式,如上圖socket處理流程所示,根據accept得到新連線以後是啟用新的程序/執行緒還是直接在原來本程序內處理,分為如下兩種方式。
一種是多程序/執行緒方式,這種方式為每一個新來的連線生成一個新的程序/執行緒來單獨處理。另外一種是IO多路複用,這種方式在一個程序/執行緒中維護所有的連線的socket,透過事件處理的方式依次處理所有連線上的網路事件。
多執行緒模型如下:
在多程序/執行緒的模型中,根據accept在新老程序中的位置又分為兩種。一種型別是accept在父程序中進行,每次accept以後,fork一個新程序或者建立一個新執行緒來處理新accept的連線。一種型別是父程序在listen呼叫以後,fork出多個程序或者建立多個執行緒分別進行accept.
IO多路複用模型如下:
IO多路複用又稱為event driven IO。就是在同一個程序內同時處理多路IO,進而提高系統吞吐量。一般是透過維護一個連線池,當某個連線有資料到達,通知程序來進行資料處理。Nginx支援多種併發連線請求,比如select,poll,epoll,kqueue(針對bsd)等等,這些請求可以透過配置檔案進行選擇。一般在linux上epoll的效率要比select,poll高很多。
綜上所述,Nginx透過本身優秀的框架設計,加上核心對並行網路處理的支援,得到了非常好的併發處理效能。