Nginx讀書筆記(4) —— HTTP模塊的數據結構

HTTP模塊的數據結構

定義HTTP模塊方式很簡單,例如:

ngx_module_t ngx_http_mytest_module;

其中,ngx_module_t是一個Nginx模塊的數據結構。下面來分析一下Nginx模塊中所有的成員,如下所示:

typedef struct ngx_module_s ngx_module_t;



struct ngx_module_s

{

/* 下面的ctx_index、index、spare0、spare1、spare2、spare3、version變量不需要在定義時賦值,可以用Nginx準備好的宏NGX_MODULE_V1來定義,它已經定義好了這7個值。

#define NGX_MODULE_V1    0, 0, 0, 0, 0, 0, 1

對於一類模塊(由下面的type成員決定類別)而言,ctx_index表示當前模塊在這類模塊中的序號。這個成員常常是由管理這類模塊的一個Nginx核心模塊設置的,對於所有的HTTP模塊而言,ctx_index是由核心模塊ngx_http_module設置的。

ctx_index非常重要,Nginx的模塊化設計非常依賴於各個模塊的順序,它們既用於表達優先級,也用於表明每個模塊的位置,藉以幫助Nginx框架快速獲得某個模塊的數據。

*/

ngx_uint_t  ctx_index;



/*index表示當前模塊在ngx_modules數組中的序號。注意,ctx_index表示的是當前模塊在一類模塊中的序號,而index表示當前模塊在所有模塊中的序號,它同樣關鍵。

Nginx啓動時會根據ngx_modules數組設置各模塊的index值。

例如:

ngx_max_module = 0;

for (i = 0; ngx_modules[i]; i++) 

{

    ngx_modules[i]->index = ngx_max_module++; 

}

*/

ngx_uint_t  index;



// spare系列的保留變量,暫未使用

ngx_uint_t spare0;

ngx_uint_t spare1;

ngx_uint_t spare2;

ngx_uint_t spare3;



// 模塊的版本,便於將來的擴展。目前只有一種,默認爲1

ngx_uint_t  version;



/*ctx用於指向一類模塊的上下文結構體,爲什麼需要ctx呢?因爲前面說過,Nginx模塊有許多種類,不同類模塊之間的功能差別很大。

例如,事件類型的模塊主要處理I/O事件相關的功能,HTTP類型的模塊主要處理HTTP應用層的功能。這樣,每個模塊都有了自己的特性,而ctx將會指向特定類型模塊的公共接口。

例如,在HTTP模塊中,ctx需要指向ngx_http_module_t結構體

*/

void  *ctx;



// commands將處理nginx.conf中的配置項

ngx_command_t  *commands;



/*type表示該模塊的類型,它與ctx指針是緊密相關的。在官方Nginx中,它的取值範圍是以下5種:

NGX_HTTP_MODULE、

NGX_CORE_MODULE、

NGX_CONF_MODULE、

NGX_EVENT_MODULE、

NGX_MAIL_MODULE。

實際上,還可以自定義新的模塊類型

*/

ngx_uint_t  type;



/*在Nginx的啓動、停止過程中,以下7個函數指針表示有7個執行點會分別調用這7種方法。對於任一個方法而言,如果不需要Nginx在某個時刻執行它,那麼簡單地把它設爲NULL空指針即可

*/

/*雖然從字面上理解應當在master進程啓動時回調init_master,但到目前爲止,框架代碼從來不會調用它,因此,可將init_master設爲NULL 

*/

ngx_int_t  (*init_master)(ngx_log_t *log);



/*init_module回調方法在初始化所有模塊時被調用。在master/worker模式下,這個階段將在啓動worker子進程前完成

*/

ngx_int_t  (*init_module)(ngx_cycle_t *cycle);



/* init_process回調方法在正常服務前被調用。在master/worker模式下,多個worker子進程已經產生,在每個worker進程的初始化過程會調用所有模塊的init_process函數

*/

ngx_int_t  (*init_process)(ngx_cycle_t *cycle);



/* 由於Nginx暫不支持多線程模式,所以init_thread在框架代碼中沒有被調用過,設爲NULL

*/

ngx_int_t  (*init_thread)(ngx_cycle_t *cycle);



//同上,exit_thread也不支持,設爲NULL

void  (*exit_thread)(ngx_cycle_t *cycle);



/* exit_process回調方法在服務停止前調用。在master/worker模式下,worker進程會在退出前調用它

*/

void  (*exit_process)(ngx_cycle_t *cycle);



//exit_master回調方法將在master進程退出前被調用

void  (*exit_master)(ngx_cycle_t *cycle);



/*以下8個spare_hook變量也是保留字段,目前沒有使用,但可用Nginx提供的NGX_MODULE_V1_PADDING宏來填充。

看一下該宏的定義:

#define NGX_MODULE_V1_PADDING  0, 0, 0, 0, 0, 0, 0, 0

*/

uintptr_t  spare_hook0;

uintptr_t  spare_hook1;

uintptr_t  spare_hook2;

uintptr_t  spare_hook3;

uintptr_t  spare_hook4;

uintptr_t  spare_hook5;

uintptr_t  spare_hook6;

uintptr_t  spare_hook7;

};

 

定義一個HTTP模塊時,務必把type字段設爲NGX_HTTP_MODULE。

對於下列回調方法:init_module、init_process、exit_process、exit_master,調用它們的是Nginx的框架代碼。換句話說,定義HTTP模塊時,最重要的是要設置ctx和commands這兩個成員。在HTTP模塊中,ctx需要指向ngx_http_module_t結構體。

HTTP框架在讀取、重載配置文件時定義了由ngx_http_module_t接口描述的8個階段。

typedef struct

{

//解析配置文件前調用

ngx_int_t  (*preconfiguration)(ngx_conf_t *cf);



//完成配置文件的解析後調用

ngx_int_t  (*postconfiguration)(ngx_conf_t *cf);



/* 當需要創建數據結構用於存儲main 級別(直屬於http{...} 塊的配置項)的全局配置項時,可以通過create_main_conf 回調方法創建存儲全局配置項的結構體

*/

void  *(*create_main_conf)(ngx_conf_t *cf);



//常用於初始化main 級別配置項

char  *(*init_main_conf)(ngx_conf_t cf, void conf);



/* 當需要創建數據結構用於存儲srv 級別(直屬於虛擬主機server{...} 塊的配置項)的配置項時,可以通過實現create_srv_conf 回調方法創建存儲srv 級別配置項的結構體

*/

void  *(*create_srv_conf)(ngx_conf_t *cf);



//merge_srv_conf 回調方法主要用於合併main 級別和srv 級別下的同名配置項

char  *(*merge_srv_conf)(ngx_conf_t cf, void prev, void *conf);



/* 當需要創建數據結構用於存儲loc 級別(直屬於location{...} 塊的配置項)的配置項時,可以實現create_loc_conf 回調方法

*/

void  *(*create_loc_conf)(ngx_conf_t *cf);



//merge_loc_conf 回調方法主要用於合併srv 級別和loc 級別下的同名配置項

char  *(*merge_loc_conf)(ngx_conf_t cf, void prev, void *conf);

} ngx_http_module_t;

 

不過,這8個階段的調用順序與上述定義的順序是不同的。在Nginx啓動過程中,HTTP框架調用這些回調方法的實際順序如下:

1)create_main_conf

2)create_srv_conf

3)create_loc_conf

4)preconfiguration

5)init_main_conf

6)merge_srv_conf

7)merge_loc_conf

8)postconfiguration

 

commands數組用於定義模塊的配置文件參數,每一個數組元素都是ngx_command_t類型,數組的結尾用ngx_null_command

typedef struct  ngx_command_s ngx_command_t; 

struct ngx_command_s 

{

//配置項名稱,如"gzip"

ngx_str_t  name;

/* 配置項類型,type 將指定配置項可以出現的位置。例如,出現在server{} 或location{} 中,以及它可以攜帶的參數個數

*/

ngx_uint_t  type;



//出現了name 中指定的配置項後,將會調用set 方法處理配置項的參數

char  *(*set)(ngx_conf_t cf, ngx_command_t cmd, void *conf);



//在配置文件中的偏移量

ngx_uint_t  conf;



/* 通常用於使用預設的解析方法解析配置項,這是配置模塊的一個優秀設計。它需要與

conf 配合使用

*/

ngx_uint_t  offset;



//配置項讀取後的處理方法,必須是ngx_conf_post_t 結構的指針

void  *post;

};

 

ngx_null_command只是一個空的ngx_command_t,如下所示:

#define ngx_null_command  { ngx_null_string, 0, NULL, 0, 0, NULL }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章