Nginx架構
nginx在啟動后,在unix系統中會以daemon的方式在后臺運行,后臺進程包含一個master進程和多個worker進程。
當然nginx也是支持多線程的方式的,只是我們主流的方式還是多進程的方式,也是nginx的默認方式。
master進程主要用來管理worker進程,包含:接收來自外界的信號,向各worker進程發送信號,監控worker進程的運行狀態,當worker進程退出后(異常情況下),會自動重新啟動新的worker進程。
worker進程則是處理基本的網絡事件。多個worker進程之間是對等的,他們同等競爭來自客戶端的請求,各進程互相之間是獨立的。一個請求,只可能在一個worker進程中處理,一個worker進程,不可能處理其它進程的請求。
worker進程的個數是可以設置的,一般我們會設置與機器cpu核數一致。更多的worker數,只會導致進程來競爭cpu資源了,從而帶來不必要的 上下文切換。而且,nginx為了更好的利用多核特性,具有cpu綁定選項,我們可以將某一個進程綁定在某一個核上,這樣就不會因為進程的切換帶來 cache的失效。
驚群現象
每個worker進程都是從master進程fork過來。在master進程里面,先建立好需要listen的socket之后,然后再fork出多 個worker進程,這樣每個worker進程都可以去accept這個socket(當然不是同一個socket,只是每個進程的這個socket會監 控在同一個ip地址與端口,這個在網絡協議里面是允許的)。一般來說,當一個連接進來后,所有在accept在這個socket上面的進程,都會收到通 知,而只有一個進程可以accept這個連接,其它的則accept失敗。
相對于線程,采用進程的優點
進程之間不共享資源,不需要加鎖,所以省掉了鎖帶來的開銷。
采用獨立的進程,可以讓互相之間不會影響,一個進程退出后,其它進程還在工作,服務不會中斷,master進程則很快重新啟動新的worker進程。
編程上更加容易。
多線程的問題
而多線程在多并發情況下,線程的內存占用大,線程上下文切換造成CPU大量的開銷。想想apache的常用工作方式(apache也有異步非阻塞版本, 但因其與自帶某些模塊沖突,所以不常用),每個請求會獨占一個工作線程,當并發數上到幾千時,就同時有幾千的線程在處理請求了。這對操作系統來說,是個不 小的挑戰,線程帶來的內存占用非常大,線程的上下文切換帶來的cpu開銷很大,自然性能就上不去了,而這些開銷完全是沒有意義的。
異步非阻塞
異步的概念和同步相對的,也就是不是事件之間不是同時發生的。
非阻塞的概念是和阻塞對應的,阻塞是事件按順序執行,每一事件都要等待上一事件的完成,而非阻塞是如果事件沒有準備好,這個事件可以直接返回,過一段時間再進行處理詢問,這期間可以做其他事情。但是,多次詢問也會帶來額外的開銷。
總的來說,Nginx采用異步非阻塞的好處在于:
-
不需要創建線程,每個請求只占用少量的內存
</li> -
沒有上下文切換,事件處理非常輕量
</li> </ul>nginx的源碼目錄結構(100%)
nginx 的優秀除了體現在程序結構以及代碼風格上,nginx的源碼組織也同樣簡潔明了,目錄結構層次結構清晰,值得我們去學習。nginx的源碼目錄與 nginx的模塊化以及功能的劃分是緊密結合,這也使得我們可以很方便地找到相關功能的代碼。這節先介紹nginx源碼的目錄結構,先對nginx的源碼 有一個大致的認識,下節會講解nginx如何編譯。
下面是nginx源碼的目錄結構:
. ├── auto 自動檢測系統環境以及編譯相關的腳本 │ ├── cc 關于編譯器相關的編譯選項的檢測腳本 │ ├── lib nginx編譯所需要的一些庫的檢測腳本 │ ├── os 與平臺相關的一些系統參數與系統調用相關的檢測 │ └── types 與數據類型相關的一些輔助腳本 ├── conf 存放默認配置文件,在make install后,會拷貝到安裝目錄中去 ├── contrib 存放一些實用工具,如geo配置生成工具(geo2nginx.pl) ├── html 存放默認的網頁文件,在make install后,會拷貝到安裝目錄中去 ├── man nginx的man手冊 └── src 存放nginx的源代碼 ├── core nginx的核心源代碼,包括常用數據結構的定義,以及nginx初始化運行的核心代碼如main函數 ├── event 對系統事件處理機制的封裝,以及定時器的實現相關代碼 │ └── modules 不同事件處理方式的模塊化,如select、poll、epoll、kqueue等 ├── http nginx作為http服務器相關的代碼 │ └── modules 包含http的各種功能模塊 ├── mail nginx作為郵件代理服務器相關的代碼 ├── misc 一些輔助代碼,測試c++頭的兼容性,以及對google_perftools的支持 └── os 主要是對各種不同體系統結構所提供的系統函數的封裝,對外提供統一的系統調用接口