Nginx 源碼分析:從模塊到配置(下)

本篇的上篇 Nginx 源碼分析:從模塊到配置(上),建議閱讀本篇前先閱讀上篇。html

關於模塊

Nginx的架構高度模塊化。每一個模塊各司其職,組合在一塊兒完成特定的功能。nginx

Nginx經過configure決定哪些模塊被安裝。全部安裝的模塊在編譯階段靜態生成,其指針被統一放入ngx_modules數組中,供全局使用。segmentfault

每一個模塊由如下幾部分構成:數組

  1. ngx_module_t結構體:表明模塊自己,其指針被放入ngx_modules數組中。
  2. ngx_<module name>_conf_t結構體:用來表示模塊的配置內容,其中部分紅員能夠經過配置文件進行配置。
  3. ngx_<module name>_module_t結構體:模塊上下文,保存了一組操做,Nginx初始化階段調用這些操做,初始化ngx_<module name>_conf_t中的成員。
  4. ngx_command_t結構體數組:該數組中每一項ngx_command_t對應配置文件中一條指令。

Nginx的模塊雖然有不少。可是基本類型只有5種:CORF、CONF、EVNT、HTTP、MAIL架構

#define NGX_CORE_MODULE      0x45524F43  /* "CORE" */
#define NGX_CONF_MODULE      0x464E4F43  /* "CONF" */
#define NGX_EVENT_MODULE     0x544E5645  /* "EVNT" */
#define NGX_HTTP_MODULE      0x50545448  /* "HTTP" */
#define NGX_MAIL_MODULE      0x4C49414D  /* "MAIL" */

每種類型對應一種ngx_<module name>_module_t上下文結構體。Nginx在初始化(主要在ngx_init_cycle函數中)時根據不一樣的模塊類型,調用不一樣的上下文中的操做,完成其配置內容的初始化。模塊化

雖然模塊類型只有5種,可是模塊數量能夠有不少,每一個模塊都針對自身有特定的配置內容,這些配置內容中,能夠被放到配置文件nginx.conf中的,被包裝成了一條條ngx_command_t指令。這些指令的內容決定了nginx.conf中能夠寫入的操做指令。函數

Nginx初始化時解析nginx.conf配置文件,找到對應的ngx_command_t。調用該ngx_command_t中的函數,該函數最終初始化模塊對應的ngx_<module name>_conf_t結構體,完成配置。源碼分析

這就是模塊和配置之間的關係。post

配置文件、指令

談到Nginx的配置,首先想到的確定是配置文件nginx.confui

衆所周知,nginx.conf配置文件的結構由一條條Nginx配置指令構成(官方文檔)。
Nginx配置指令能夠分爲兩種:簡單指令和塊指令。

例如:

  • worker_processes 1;就是一條簡單指令
  • events { ... }就是一條塊指令

若是,一個塊指令中含有其餘指令,那麼稱這個塊指令爲上下文(注意區別模塊中的上下文概念)。
例如:

events {
      use epoll;
      worker_connections  1024;
 }

events是塊指令,因爲events中包含有指令(簡單指令或塊指令)。所以稱eventsevents上下文

常見的上下文還有:http上下文、server上下文、location上下文整個nginx.conf文件稱爲main上下文

源碼中的配置指令

前面提到過:Nginx配置文件中的一條指令對應一個ngx_command_t結構體。所以,分析源碼中的配置指令,就是分析ngx_command_t結構體。

ngx_command_t結構體定義:

struct ngx_command_s {
    ngx_str_t             name;
    ngx_uint_t            type;
    char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
    ngx_uint_t            conf;
    ngx_uint_t            offset;
    void                 *post;
};

各成員含義以下:

name:本條指令的名字,例如worker_processes 1;對應的ngx_command_s.name就是worker_processes

set:函數指針,因此set用來表示,當Nginx解析配置文件,碰到指令時,該執行怎樣的操做。而該操做自己,天然是用來設置本模塊所對應的ngx_<module name>_conf_t結構體。

conf:這個變量只在NGX_HTTP_MODULE類型的模塊的ngx_command_t使用。這個變量和今天討論的話題關係不大。暫不討論。

offset:這個變量用來標記ngx_<module name>_conf_t中某成員變量的偏移量,純粹是爲使用方便。

type:配置指令屬性的集合。例如,worker_processes這條指令對應的type定義爲:

NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1

其中,各個宏定義以下:

#define NGX_MAIN_CONF        0x01000000
#define NGX_DIRECT_CONF      0x00010000
#define NGX_CONF_TAKE1       0x00000002
  • NGX_MAIN_CONF是指,該指令用於main上下文
  • NGX_DIRECT_CONF是指,該指令是用於main上下文的簡單指令
  • NGX_CONF_TAKE1是指,該指令後跟一個參數,例如worker_processes 1;1就是指後面跟一個參數,這個參數的數目由NGX_CONF_TAKE1指定。

相似用來定義指令類型的宏還有不少,具體能夠參考源碼中各個模塊中ngx_command_t的設置。

幾個典型的配置指令

daemon指令

Nginx默認是之後臺的形式運行的,這種運行形式被稱爲daemon,固然,在調試的時候,爲了方便,通常是關掉daemon這種運行形式。

在配置文件中經過daemon指令來打開或關閉。官方文檔對daemon指令說明以下:

Syntax:     daemon on | off;
Default:    daemon on;
Context:    main

在源碼中(core\nginx.c),daemon指令對應的ngx_command_t結構體以下:

{ngx_string("daemon"),                              // 指令的名字daemon
      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,       // 指令的類型
      ngx_conf_set_flag_slot,                            // 指令對應的操做
      0,
      offsetof(ngx_core_conf_t, daemon),
      NULL }

其中,NGX_MAIN_CONF指,daemon指令的上下文爲main上下文
NGX_DIRECT_CONF指,daemon指令是一條能夠直接寫在main上下文的簡單指令。
NGX_CONF_FLAG指,daemon指令是一個開關指令,接收on | off做爲指令參數。

user指令

Nginx能夠在配置文件中經過user指令指定運行時所在的用戶及用戶組。官方文檔對user指令的說明以下:

Syntax:     user user [group];
Default:    user nobody nobody;
Context:    main

在源碼中(core\nginx.c),user對應的ngx_command_t結構體定義以下:

{ ngx_string("user"),
      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE12,
      ngx_set_user,
      0,
      0,
      NULL },

其中NGX_MAIN_CONFNGX_DIRECT_CONF的含義與daemon指令的含義相同。
NGX_CONF_TAKE12是指該指令接收1個或兩個參數,即Syntax: user user [group];

events指令

Nginx中能夠指定採用的事件監聽機制類型,好比select、poll、epoll等。
這個指定操做在events指令中完成。這裏events指令爲塊指令

官方文檔對events指令的定義以下:

Syntax:     events { ... }
Default:    —
Context:    main

在源碼中(event\ngx_event.c),events指令對應的ngx_command_t結構體定義以下:

{ ngx_string("events"),
      NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
      ngx_events_block,
      0,
      0,
      NULL }

其中,NGX_MAIN_CONF的含義與daemon指令相同。
NGX_CONF_BLOCK是指,這是一條塊指令
NGX_CONF_NOARGS是指,該指令不接受參數。

總結

以上三條指令可以很清楚的說明,在Nginx源碼中是如何組織和管理配置文件中使用的配置指令的。
對於其餘指令,能夠直接閱讀源碼中該指令的定義。源碼就是最好的文檔。

關於模塊和配置的總結

因爲Nginx是高度模塊化的,於是,Nginx的配置必定是對模塊的配置

Nginx的每條配置指令對應某模塊中的一條ngx_command_t定義。

每條ngx_command_t必定操做了其所在模塊的ngx_<module name>_conf_t結構體中某些項。

Nginx初始化時,首先解析配置文件,而後執行對應指令的ngx_command_t中的操做函數,設置ngx_<module name>_conf_t中的某些項,完成配置工做。

而後,Nginx根據這些配置,執行啓動流程,進而開始工做。

到此爲止。本篇結束。

相關文章
相關標籤/搜索