淺談Nginx服務器的內部核心架構設計

前言

Nginx 是一個 免費的開源的高性能HTTP 服務器和 反向代理,以及 IMAP / POP3 代理服務器。 Nginx 以其高性能,穩定性,豐富的功能,簡單的配置和低資源消耗而聞名。Nginx是一個 Web 服務器,也能夠用做 反向代理負載均衡器HTTP 緩存編程

不少高知名度的網站都使用 Nginx,如:NetflixGitHubSoundCloudMaxCDN 等。windows

正文

1. Nginx的總體架構

1.1. 主進程

Nginx 啓動時,會生成兩種類型的 進程*,一個是 主進程master),一個windows 版本的目前只有一個)或 多個工做進程worker)。主進程 並不處理網絡請求,主要負責 調度工做進程,也就是圖示的 3 項:加載配置啓動工做進程非停升級。因此,Nginx 啓動之後,查看操做系統的進程列表,咱們就能看到 至少有兩個 Nginx 進程。後端

1.2. 工做進程

服務器實際 處理網絡請求響應 的是 工做進程worker),在類 unix 系統上,Nginx 能夠配置 多個 worker,而每一個 worker 進程 均可以同時處理 數以千計網絡請求緩存

1.3. 模塊化設計

Nginxworker 進程,包括 核心功能性模塊核心模塊 負責維持一個 運行循環run-loop),執行網絡請求處理的 不一樣階段 的模塊功能,好比:網絡讀寫存儲讀寫內容傳輸外出過濾,以及 將請求發往上游服務器 等。而其代碼的 模塊化設計,也使得咱們能夠根據須要對 功能模塊 進行適當的 選擇修改,編譯成具備 特定功能 的服務器。安全

1.4. 事件驅動模型

基於 異步及非阻塞事件驅動模型,能夠說是 Nginx 得以得到 高併發高性能 的關鍵因素,同時也得益於對 LinuxSolaris 及類 BSD 等操做系統內核中 事件通知I/O 性能加強功能 的採用,如 kqueueepollevent ports服務器

1.5. 代理(proxy)設計

代理設計,能夠說是 Nginx 深刻骨髓的設計,不管是對於 HTTP,仍是對於 FastCGIMemcacheRedis 等的網絡請求或響應,本質上都採用了 代理機制。因此,Nginx 天生就是高性能的 代理服務器網絡

2. Nginx的模塊化設計

高度模塊化 的設計是 Nginx 的架構基礎。Nginx 服務器被分解爲 多個模塊,每一個模塊就是一個 功能模塊,只負責自身的功能,模塊之間嚴格遵循 「高內聚,低耦合」 的原則。多線程

2.1. 核心模塊

核心模塊Nginx 服務器正常運行 必不可少 的模塊,提供 錯誤日誌記錄配置文件解析事件驅動機制進程管理 等核心功能。架構

2.2. 標準HTTP模塊

標準 HTTP 模塊提供 HTTP 協議解析相關的功能,好比:端口配置網頁編碼設置HTTP 響應頭設置 等等。併發

2.3. 可選HTTP模塊

可選 HTTP 模塊主要用於 擴展 標準的 HTTP 功能,讓 Nginx 能處理一些特殊的服務,好比:Flash 多媒體傳輸、解析 GeoIP 請求、網絡傳輸壓縮安全協議 SSL 支持等。

2.4. 郵件服務模塊

郵件服務模塊 主要用於支持 Nginx郵件服務,包括對 POP3 協議、IMAP 協議和 SMTP 協議的支持。

2.5. 第三方模塊

第三方模塊 是爲了擴展 Nginx 服務器應用,完成開發者自定義功能,好比:Json 支持、Lua 支持等。

3. Nginx的請求方式處理

Nginx 是一個 高性能Web 服務器,可以同時處理 大量的併發請求。它結合 多進程機制異步機制,異步機制使用的是 異步非阻塞方式,接下來就給你們介紹一下 Nginx多線程機制異步非阻塞機制

3.1. 多進程機制

服務器每當收到一個客戶端時,就有 服務器主進程master process)生成一個 子進程worker process)出來和客戶端創建鏈接進行交互,直到鏈接斷開,該子進程就結束了。

使用 進程 的好處是 各個進程之間相互獨立不須要加鎖,減小了使用鎖對性能形成影響,同時下降編程的複雜度,下降開發成本。其次,採用獨立的進程,可讓 進程互相之間不會影響,若是一個進程發生異常退出時,其它進程正常工做,master 進程則很快啓動新的 worker 進程,確保服務不會中斷,從而將風險降到最低。

缺點是操做系統生成一個 子進程 須要進行 內存複製 等操做,在 資源時間 上會產生必定的開銷。當有 大量請求 時,會致使 系統性能降低

3.2. 異步非阻塞機制

每一個 工做進程 使用 異步非阻塞方式,能夠處理 多個客戶端請求

當某個 工做進程 接收到客戶端的請求之後,調用 IO 進行處理,若是不能當即獲得結果,就去 處理其餘請求(即爲 非阻塞);而 客戶端 在此期間也 無需等待響應,能夠去處理其餘事情(即爲 異步)。

IO 返回時,就會通知此 工做進程;該進程獲得通知,暫時 掛起 當前處理的事務去 響應客戶端請求

4. Nginx事件驅動模型

Nginx異步非阻塞機制 中,工做進程 在調用 IO 後,就去處理其餘的請求,當 IO 調用返回後,會 通知工做進程。對於這樣的系統調用,主要使用 Nginx 服務器的 事件驅動模型 來實現。

如上圖所示,Nginx事件驅動模型事件收集器事件發送器事件處理器 三部分基本單元組成。

  • 事件收集器:負責收集 worker 進程的各類 IO 請求;

  • 事件發送器:負責將 IO 事件發送到 事件處理器

  • 事件處理器:負責各類事件的 響應工做

事件發送器 將每一個請求放入一個 待處理事件列表,使用非阻塞 I/O 方式調用 事件處理器 來處理該請求。其處理方式稱爲 「多路 IO 複用方法」,常見的包括如下三種:select 模型、poll 模型、epoll 模型。

5. Nginx進程處理模型

Nginx 服務器使用 master/worker 多進程模式。多線程啓動和執行的流程以下:

  1. 主程序 Master process 啓動後,經過一個 for 循環來 接收處理外部信號

  2. 主進程 經過 fork() 函數產生 worker 子進程,每一個 子進程 執行一個 for 循環來實現 Nginx 服務器 對事件的接收處理

通常推薦 worker 進程數CPU 內核數 一致,這樣一來不存在 大量的子進程 生成和管理任務,避免了進程之間 競爭 CPU 資源進程切換 的開銷。並且 Nginx 爲了更好的利用 多核特性,提供了 CPU 親緣性 的綁定選項,咱們能夠將某 一個進程綁定在某一個核 上,這樣就不會由於 進程的切換 帶來 Cache 的失效。

對於每一個請求,有且只有一個 工做進程 對其處理。首先,每一個 worker 進程都是從 master 進程 fork 過來。在 master 進程裏面,先創建好須要 listensocket(listenfd) 以後,而後再 fork 出多個 worker 進程。

全部 worker 進程的 listenfd 會在 新鏈接 到來時變得 可讀,爲保證只有一個進程處理該鏈接,全部 worker 進程在註冊 listenfd 讀事件搶佔 accept_mutex,搶到 互斥鎖 的那個進程 註冊 listenfd 讀事件,在 讀事件 裏調用 accept 接受該鏈接。

當一個 worker 進程在 accept 這個鏈接以後,就開始 讀取請求解析請求處理請求,產生數據後,再 返回給客戶端,最後才 斷開鏈接,這樣一個完整的請求就是這樣的了。咱們能夠看到,一個請求,徹底由 worker 進程來處理,並且只在一個 worker 進程中處理。

Nginx 服務器的運行過程當中,主進程工做進程 須要進程交互。交互依賴於 Socket 實現的 管道 來實現。

5.1. 主進程與工做進程交互

這條管道與普通的管道不一樣,它是由 主進程 指向 工做進程單向管道,包含主進程向工做進程發出的 指令工做進程 ID 等;同時 主進程 與外界經過 信號通訊;每一個 子進程 具有 接收信號,並處理相應的事件的能力。

5.2. 工做進程與工做進程交互

這種交互是和 主進程-工做進程 交互是基本一致的,可是會經過 主進程 間接完成。工做進程 之間是 相互隔離 的,因此當工做進程 W1 須要向工做進程 W2 發指令時,首先找到 W2進程 ID,而後將正確的指令寫入指向 W2通道W2 收到信號採起相應的措施。

小結

經過這篇文章,咱們對 Nginx 服務器的 總體架構 有了一個總體的認識。包括其 模塊化的設計多進程異步非阻塞 的請求處理方式、事件驅動模型 等。經過這些理論知識,才能更好地領悟 Nginx 的設計思想。對於咱們學習 Nginx 來講有很大的幫助。


歡迎關注技術公衆號: 零壹技術棧

零壹技術棧

本賬號將持續分享後端技術乾貨,包括虛擬機基礎,多線程編程,高性能框架,異步、緩存和消息中間件,分佈式和微服務,架構學習和進階等學習資料和文章。

相關文章
相關標籤/搜索