Nginx Http架構的理解

來源:互聯網
上載者:User

標籤:div   master   and   問題   pre   block   strong   命名   儲存位置   

HTTP架構是Nginx基礎架構的一部分,Nginx的其它底層架構如master-worker進程模型、event模組、mail 模組等。

HTTP架構代碼主要有2個模組組成:ngx_http_module和ngx_http_core_module;

我們編寫的HTTP模組需要註冊到HTTP架構上,才能融入HTTP請求的處理流程中。

當在nginx.conf中存在一個http{...}的配置時,即啟用了HTTP架構代碼,在nginx配置解析時,就已經為架構建立好了各種資料結構(尤其是HTTP模組的掛載);

當nginx收到請求時,請求完全按照HTTP架構建立好的這種邏輯進行處理。

 

 

一、HTTP模組開發基礎

開發一個HTTP模組,需要下面幾個資料結構:

 

1. HTTP模組配置結構
用於儲存從設定檔讀進來的相關指令參數;配置模組的context有三種,分別是main、server和location,它們分別位于于http{...}、server{...}和location{...}上下文中。其名稱約定如下: ngx_http_<module name>_(main|srv|loc)_conf_t 2.HTTP 模組配置指令模組的指令是定義在一個叫做 ngx_command_t的靜態數組中的;ngx_command_t數組以ngx_null_command為終結符。 struct ngx_command_t {
    ngx_str_t             name;          // 指令名稱
    ngx_uint_t            type;          // 指令所在的context和包含的參數個數
    char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);     // 解析配置,並將參數存入模組配置結構體中
    ngx_uint_t            conf;          // 指令參數的儲存位置
    ngx_uint_t            offset;        // 指令參數的儲存位移量
    void                 *post;     
};其中, type 成員表明這個指令允許出現的context、參數個數:    * NGX_HTTP_MAIN_CONF:   指令出現在main配置部分是合法的    * NGX_HTTP_SRV_CONF:      指令在server配置部分出現是合法的 config    * NGX_HTTP_LOC_CONF:      指令在location配置部分出現是合法的    * NGX_HTTP_UPS_CONF:      指令在upstream配置部分出現是合法的    * NGX_CONF_NOARGS:        指令沒有參數    * NGX_CONF_TAKE1:           指令讀入1個參數    * NGX_CONF_TAKE7:           指令讀入7個參數   * NGX_CONF_FLAG:             指令讀入1個布爾型資料 ("on" or "off")    * NGX_CONF_1MORE:           指令至少讀入1個參數    * NGX_CONF_2MORE:           指令至少讀入2個參數  set 成員是一個函數指標,用於模組參數解析,可以將設定檔中的模組參數傳遞給模組;該函數會在遇到指令時執行,函數有三個入參:    a. 指向結構體 ngx_conf_t 的指標, 這個結構體裡包含需要傳遞給指令的參數
   b. 指向結構體 ngx_command_t 的指標
   c. 指向模組自訂配置結構體的指標 Nginx內部提供了多個函數用來儲存特定類型的資料,這些函數包括:    * ngx_conf_set_flag_slot:      將 "on" or "off" 轉換成 1 or 0    * ngx_conf_set_str_slot:           將字串儲存為 ngx_str_t    * ngx_conf_set_num_slot:       解析一個數字並儲存為int    * ngx_conf_set_size_slot:        解析一個資料大小(如:"8k", "1m") 並儲存為size_t  conf 成員告訴Nginx把資料存在模組的哪個context中     * NGX_HTTP_MAIN_CONF_OFFSET     * NGX_HTTP_SRV_CONF_OFFSET     * NGX_HTTP_LOC_CONF_OFFSET offset 成員確定儲存在結構體的哪個位置; post 成員指向模組在讀配置的時候需要的一些零碎變數,一般為NULL。 3. HTTP模組上下文結構
靜態 ngx_http_module_t結構體,用來建立和合并三段context (main,server,location),其命名方式一般是:ngx_http_<module name>_module_ctx,typedef struct {
    ngx_int_t   (*preconfiguration)(ngx_conf_t *cf);                                         //   在讀入配置前調用
    ngx_int_t   (* postconfiguration)(ngx_conf_t *cf);                                       //  在讀入配置後調用,用於掛載handler
    void       *(*create_main_conf)(ngx_conf_t *cf);                                            // 在建立main配置時調用(比如,用來分配空間和設定預設值)
    char       *(*init_main_conf)(ngx_conf_t *cf, void *conf);                            // 在初始化main配置時調用(比如,把原來的預設值用nginx.conf讀到的值來覆蓋)
    void       *(*create_srv_conf)(ngx_conf_t *cf);                                           // 在建立server配置時調用
    char       *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);          // 合并server和main配置時調用
    void       *(* create_loc_conf)(ngx_conf_t *cf);                                        // 建立location配置時調用,用於為指令參數結構體分配記憶體和初始化
    char       *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);         // 合并location和server配置時調用 
} ngx_http_module_t;

這些回調是在ngx_http_block()解析http{...}配置時完成的:

當遇到一個 http{...} 時,HTTP架構會調用所有HTTP模組可能實現的create_main_conf、create_srv_conf、create_loc_conf產生儲存main層級配置參數結構體;

當遇到一個server{...}時,HTTP架構會調用所有HTTP模組可能實現的create_srv_conf、create_loc_conf產生儲存server層級配置參數結構體;

當遇到一個location{...}時,HTTP架構會調用所有HTTP模組可能實現的create_loc_conf產生儲存location層級配置參數結構體;

因此,我們開發的HTTP模組中create_loc_conf方法被調用的次數等於http{...}、server{...}、location{...}在nginx.conf出現的次數之和;

create_srv_conf方法被調用的次數等於server{...}、location{...}在nginx.conf出現的次數之和;

由於只有一個http{...},所以create_main_conf方法只會被調用一次;

HTTP建立了如此多的結構體來存放配置項,是為瞭解決同名配置項的合并問題。

 

4、HTTP模組定義一個Nginx模組被定義為一個 ngx_module_t 結構,該結構體變數命名方式為ngx_http_<module-name>_module它包含模組的內容和指令執行方式,同時還包含一些回呼函數來處理線程/進程的建立和銷毀;模組定義在有的時候會被用作尋找的關鍵字,來尋找與特定模組相關聯的資料。

struct ngx_module_s {
ngx_uint_t ctx_index;    // 在所有的HTTP模組中的序號
ngx_uint_t index;      // 在所有模組中的序號

ngx_uint_t spare0;
ngx_uint_t spare1;
ngx_uint_t spare2;
ngx_uint_t spare3;

ngx_uint_t version;

void *ctx;            // 模組上下文
ngx_command_t *commands;  // 模組配置指令
ngx_uint_t type;        // 模組類型,HTTP模組應為NGX_HTTP_MODULE

ngx_int_t (*init_master)(ngx_log_t *log);

ngx_int_t (*init_module)(ngx_cycle_t *cycle);

ngx_int_t (*init_process)(ngx_cycle_t *cycle);
ngx_int_t (*init_thread)(ngx_cycle_t *cycle);
void (*exit_thread)(ngx_cycle_t *cycle);
void (*exit_process)(ngx_cycle_t *cycle);

void (*exit_master)(ngx_cycle_t *cycle);

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;
};

 

注意:在configure之後產生的檔案 objs/ngx_modules.c 中包含了模組的編譯順序。

 

 

1、解析HTTP配置的流程

首先要理解 ngx_conf_parse() 的遞迴解析流程;

nginx在解析nginx.conf的時候,沒讀取一行配置項,就執行該配置項的解析回調(handler);

Nginx Http架構的理解

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.