Nginx 學習筆記--程式與模組

WormOfTime發表於2020-04-07

程式與模組(一)

簡介

Nginx 的程式碼是由一個 核心 和一系列的 模組 組成。

Nginx 由核心和一系列模組組成:核心提供web服務的基本功能,如啟用網路協議、建立執行環境、接收和分配客戶端請求、處理模組之間的互動。模組實現Nginx的各種功能和操作,Nginx的模組從結構上分為核心模組、基礎模組和第三方模組。

  • 核心模組:HTTP模組、EVENT模組和MAIL模組
  • 基礎模組:HTTP Access模組、HTTP FastCGI模組、HTTP Proxy模組和HTTP Rewrite模組
  • 第三方模組:HTTP Upstream Request Hash模組、Notice模組和HTTP Access Key模組及使用者自己開發的模組

這樣的設計使 Nginx 方便開發和擴充套件,也正因此才使得 Nginx 功能如此強大。Nginx 的模組預設編譯進 Nginx 中,如果需要增加或刪除模組,需要重新編譯 Nginx,這一點不如 Apache 的動態載入模組方便。如果有需要動態載入模組,可以使用由淘寶網發起的 Web 伺服器 Tengine,在 Nginx 的基礎上增加了很多高階特性,完全相容 Nginx,已被國內很多網站採用。

程式

首先我們要知道 Nginx 是以多程式的方式進行工作的。Nginx在Linux系統啟動後,會以守護程式(daemon)的方式在後臺執行,後臺程式包括一個 master 程式和多個 worker 程式。

  • master 程式

master程式主要用來管理worker程式,master的工作:接收來自外界的訊號,向各worker程式傳送訊號,監控worker程式的執行狀態,當worker程式退出後(異常關閉下),重新開啟新的worker程式。

master 程式主要完成如下工作:

  • 讀取並驗證配置資訊

  • 建立、繫結及關閉套接字

  • 啟動、終止worker程式及維護worker程式的個數

  • 無須終止服務而重新配置工作

  • 控制非中斷式程式升級、啟用新的二進位制程式及在有需要時回滾至老版本

  • 重新開啟日誌檔案

  • 編譯嵌入式Perl指令碼

  • worker 程式

對於基本的網路請求,Nginx則是放在worker程式來處理。多個worker程式之間是對等的,他們同等競爭來自客戶端的請求,各程式之間相互獨立。

一個請求,只能在一個worker程式中處理, 一個worker程式,不可能處理其它程式的請求。之間的關係是一對一。

Nginx在啟動時,建立一組初始的監聽套接字,HTTP 請求和響應之時,worker 連續接收、讀取和寫入套接字。

worker 程式主要完成如下工作:

  • 接收、傳入並處理來自客戶端的請求
  • 提供反向代理及過濾功能
  • nginx任何能完成的其他任務

既然 worker 程式之間是平等的,每個程式,處理請求的機會也是一樣的。當我們提供 80 埠的 http 服務時,一個連線請求過來,每個程式都有可能處理這個連線。那麼問題來了,到底最後怎樣處理,是由什麼決定的呢?我們來看一看一個完整的請求是怎樣通過互相的協作來實現的:

  1. 首先,每個 worker 程式都是從 master 程式 fork 過來,在 master 程式裡面,先建立好需要 listensocketlistenfd)之後,然後再 fork 出多個 worker 程式。
  2. 所有 worker 程式的 listenfd 會在新連線到來時變得可讀,為保證只有一個程式處理該連線,所有 worker 程式會在註冊 listenfd 讀事件前搶 accept_mutex,搶到互斥鎖的那個程式註冊 listenfd 讀事件,然後在讀事件裡呼叫 accept 接受該連線。
  3. 當一個 worker 程式在 accept 這個連線之後,就開始讀取請求、解析請求、處理請求。產生資料後,再返回給客戶端,最後才斷開連線,這樣一個完整的請求就是這樣的了。

我們可以看到:一個請求,完全由 worker 程式來處理,而且只在一個 worker 程式中處理。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章