作者:我最喜歡三大框架
來源:https://my.oschina.net/u/3906190/blog/1859060

前言

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

很多高知名度的網站都使用 Nginx ,如: Netflix , GitHub , SoundCloud , MaxCDN 等。

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

正文

1. Nginx的整體架構

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

1.1. 主進程

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

1.2. 工作進程

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

1.3. 模塊化設計

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

1.4. 事件驅動模型

基於 異步及非阻塞事件驅動模型 ,可以說是 Nginx 得以獲得 高併發高性能 的關鍵因素,同時也得益於對 Linux 、 Solaris 及類 BSD 等操作系統內核中 事件通知 及 I/O 性能增強功能 的採用,如 kqueue 、 epoll 及 event ports 。

1.5. 代理(proxy)設計

代理設計,可以說是 Nginx 深入骨髓的設計,無論是對於 HTTP ,還是對於 FastCGI 、 Memcache 、 Redis 等的網絡請求或響應,本質上都採用了 代理機制 。所以, Nginx 天生就是高性能的 代理服務器

2. Nginx的模塊化設計

高度模塊化的設計是 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 服務器的內部核心架構設計

如上圖所示, 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 進程裏面,先建立好需要 listen 的 socket(listenfd) 之後,然後再 fork 出多個 worker 進程。

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

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

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

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

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

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

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

這種交互是和 主進程-工作進程 交互是基本一致的,但是會通過 主進程 間接完成。 工作進程之間是 相互隔離 的,所以當工作進程 W1 需要向工作進程 W2 發指令時,首先找到 W2 的 進程ID ,然後將正確的指令寫入指向 W2 的 通道 。 W2 收到信號採取相應的措施。

小結

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

34張架構史上最全技術知識圖譜

相關文章