Nginx的請(qǐng)求上下文

Nginx的配置項(xiàng)

nginx 在每一個(gè)http 塊, server 塊, location 塊下, 都會(huì)生成獨(dú)立的數(shù)據(jù)結(jié)構(gòu)用來存放配置項(xiàng)

使用Http配置

  • 處理http 配置項(xiàng)的基本流程:
    • 創(chuàng)建數(shù)據(jù)結(jié)構(gòu), 存儲(chǔ)配置項(xiàng)參數(shù)
    • 設(shè)定nginx.conf中配置項(xiàng)的限制條件與回掉方法
    • 實(shí)現(xiàn)上一步中的回掉函數(shù), 或者使用預(yù)設(shè)的14種方法
    • 合并不同級(jí)別的配置塊中出現(xiàn)的同名配置項(xiàng)

分配用于保存配置參數(shù)的數(shù)據(jù)結(jié)構(gòu)

  • 數(shù)據(jù)結(jié)構(gòu)可以根據(jù)自己的項(xiàng)目的需求進(jìn)行定義, nginx有14 種預(yù)設(shè)配置項(xiàng), 設(shè)計(jì)了如下數(shù)據(jù)結(jié)構(gòu):
typedef struct { 
  ngx_str_t my_str; 
  ngx_int_t my_num; 
  ngx_flag_t my_flag; 
  size_t my_size; 
  ngx_array_t * my_str_array; 
  ngx_array_t * my_keyval; 
  off_t my_off; 
  ngx_msec_t my_msec; 
  time_t my_sec; 
  ngx_bufs_t my_bufs; 
  ngx_uint_t my_enum_seq; 
  ngx_uint_t my_bitmask; 
  ngx_uint_t my_access; 
  ngx_path_t * my_path; 
} ngx_http_mytest_conf_t; 
  • nginx設(shè)計(jì)在HTTP 框架解析nginx.conf 文件的時(shí)候, 只要遇到 http{}, server{}, location{} 配置塊, 就會(huì)立即分配一個(gè)結(jié)構(gòu)體用來存儲(chǔ)配置參數(shù), 進(jìn)程中可能會(huì)有多個(gè)這樣的配置實(shí)例存在, 因而, 需要定義上述這個(gè)結(jié)構(gòu)體, 便于參數(shù)管理。通過ngx_http_module_t 中所定義的回調(diào)方法, 我們可以操作 這個(gè)結(jié)構(gòu)體 。
    • 當(dāng)框架遇到 http{} 的時(shí)候, 調(diào)用HTTP 模塊可能實(shí)現(xiàn)的create_main_conf, create_srv_conf, create_loc_conf 生成存儲(chǔ)main級(jí)別配置參數(shù)的結(jié)構(gòu)體
    • 同理,遇到 server{} 的時(shí)候, 調(diào)用 create_srv_conf, create_loc_conf 生成存儲(chǔ) srv 級(jí)別配置參數(shù)的結(jié)構(gòu)體
    • 遇到 location{}時(shí), 調(diào)用 create_loc_conf 生成 loc 級(jí)別配置參數(shù)的存儲(chǔ)結(jié)構(gòu)
  • **一般普通的HTTP 模塊往往只實(shí)現(xiàn)create_loc_conf回調(diào)方法, 因?yàn)椋?他們一般只關(guān)心匹配某種URL的請(qǐng)求 **


設(shè)定配置項(xiàng)的解析方式

nginx中,配置項(xiàng)主要通過ngx_command_t結(jié)構(gòu)進(jìn)行解析。


  • 關(guān)于type 的設(shè)置具體可以參考官方文檔: https://www.nginx.com/resources/wiki/extending/api/configuration/?highlight=ngx_command_t#

  • set 回調(diào)方法, 是用來處理nginx.conf 中的配置項(xiàng)的, 這部分可以使用14種預(yù)設(shè)的方法

  • conf, 用來指示配置項(xiàng)所處內(nèi)存的相對(duì)偏移位置。

    • 因?yàn)椋?HTTP 模塊中可能定義了 3 個(gè)結(jié)構(gòu)體, 用來存儲(chǔ)main, srv, loc 級(jí)別的配置項(xiàng) (對(duì)應(yīng) create_main_conf, create_srv_conf, create_loc_conf), 這里使用 conf 用來指明, 將解析出來的配置項(xiàng)的值存放到哪個(gè)結(jié)構(gòu)體中
    • 對(duì)conf 的設(shè)置是與ngx_http_module_t 實(shí)現(xiàn)的回調(diào)方法相關(guān)的。
    • 功能較為簡(jiǎn)單的HTTP 模塊都只實(shí)現(xiàn)了create_loc_conf 的回調(diào)方法, 對(duì)于 http{}, server{} 塊內(nèi)出現(xiàn)的同名配置項(xiàng), 都是并入到某個(gè)location{} 內(nèi)create_loc_conf 方法所產(chǎn)生的結(jié)構(gòu)體中的。 如果希望, 在HTTP 模塊中的代碼保存到不同的變量中, 就需要實(shí)現(xiàn)create_mian_conf, create_srv_conf
  • offset, 用來表明當(dāng)前配置項(xiàng)在整個(gè)存儲(chǔ)配置項(xiàng)的結(jié)構(gòu)體中的偏移位置, 可以借助 offsetof 宏實(shí)現(xiàn)這個(gè)計(jì)算的過程

  • post, 配置項(xiàng)處理后的后續(xù)方法。

自定義配置項(xiàng)處理方法

  • 首先自定義存儲(chǔ)結(jié)構(gòu)體
  • 編寫set 方法
 static char * ngx_conf_set_myconfig(ngx_conf_t * cf, ngx_command_t * cmd, void * conf);
  • 其中, conf 指代的就是我們自定義的存儲(chǔ)結(jié)構(gòu)體 然后通過, cf->args->elfs 獲取參數(shù)隊(duì)列
static char* ngx_conf_set_myconfig(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    //注意,參數(shù)conf就是http框架傳給我們的,在ngx_http_mytest_create_loc_conf
//回調(diào)方法中分配的結(jié)構(gòu)體ngx_http_mytest_conf_t
    ngx_http_mytest_conf_t  *mycf = conf;

    // cf->args是1個(gè)ngx_array_t隊(duì)列,它的成員都是ngx_str_t結(jié)構(gòu)。
//我們用value指向ngx_array_t的elts內(nèi)容,其中value[1]就是第1
//個(gè)參數(shù),同理value[2]是第2個(gè)參數(shù)
    ngx_str_t* value = cf->args->elts;

    //ngx_array_t的nelts表示參數(shù)的個(gè)數(shù)
    if (cf->args->nelts > 1)
    {
        //直接賦值即可, ngx_str_t結(jié)構(gòu)只是指針的傳遞
        mycf->my_config_str = value[1];
    }
    if (cf->args->nelts > 2)
    {
        //將字符串形式的第2個(gè)參數(shù)轉(zhuǎn)為整型
        mycf->my_config_num = ngx_atoi(value[2].data, value[2].len);
        //如果字符串轉(zhuǎn)化整型失敗,將報(bào)"invalid number"錯(cuò)誤,
//nginx啟動(dòng)失敗
        if (mycf->my_config_num == NGX_ERROR)
        {
            return "invalid number";
        }
    }

    //返回成功
    return NGX_CONF_OK;
}

合并配置項(xiàng)

如果http{}, server{}, location{} 下面都出現(xiàn)了同名的配置項(xiàng), 根據(jù) merge_loc_conf(merge_srv_conf)進(jìn)行合并, 如果他們被設(shè)置為 null, * 忽略上一級(jí)中的同名配置項(xiàng) *

// cf 表示全局配置的設(shè)置, prev 表示父級(jí)配置結(jié)構(gòu)體, void * conf 為當(dāng)前配置結(jié)構(gòu)體
char * (*merge_loc_conf)(ngx_conf_t * cf, void * prev, void * conf)

HTTP 配置模型

  • 當(dāng)nginx 檢測(cè)到 http{} 關(guān)鍵配置的時(shí)候, HTTP 配置模型啟動(dòng), 首先建立一個(gè)ngx_http_conf_ctx_t 的上下文結(jié)構(gòu)
typedef struct {
    void ** main_conf;
    void ** srv_conf;
    void ** loc_conf; // 指針數(shù)組, 數(shù)組的每個(gè)元素指向相應(yīng) HTTP 模塊 的 create_loc_conf 方法產(chǎn)生的結(jié)構(gòu)體的地址
} ngx_http_conf_ctx_t;

HTTP 框架為所有的HTTP 模塊建立 3個(gè)數(shù)組, 分別存放 create_main_conf, create_srv_conf, create_loc_conf 方法所返回的地址指針。即ngx_http_conf_ctx_t 結(jié)構(gòu)保存了所有HTTP 模塊的配置數(shù)據(jù)結(jié)構(gòu)的入口。

解析HTTP 配置的流程

  • 對(duì)于每一個(gè)server 塊, location 塊, http 塊 都會(huì)建立一個(gè)相應(yīng)的 ngx_http_conf_ctx_t 的結(jié)構(gòu)

HTTP配置模型的內(nèi)存結(jié)構(gòu)


  • 通過上面的圖, 我們可以知道, nginx.conf中 http{}, server{}, location{} 的總個(gè)數(shù) 與 調(diào)用create_loc_conf方法的次數(shù)相同; 而 http{}, server{} 的總個(gè)數(shù) 與 調(diào)用create_srv_conf 方法的次數(shù)相同。 而這些方法每被調(diào)用一次就生成一個(gè)結(jié)構(gòu)體。 (便于解決同名配置項(xiàng)的合并問題)。
  • 調(diào)用 merge_srv_conf, 和 merge_loc_conf 進(jìn)行配置項(xiàng)合并

預(yù)設(shè)配置項(xiàng)處理方法的工作原理

  • 通過 使用 cf->args->elts 直接獲取配置參數(shù)
  • nginx 配置項(xiàng)解析模塊在調(diào)用 ngx_command_t 結(jié)構(gòu)體的set 方法的時(shí)候, 會(huì)同時(shí)把offset 編譯傳遞進(jìn)來。由此, 可以正確識(shí)別需要解析的配置項(xiàng)的存儲(chǔ)位置

error日志

  • 可以使用 ngx_log_error / ngx_log_debug 進(jìn)行日志記錄

請(qǐng)求上下文

  • 在一個(gè)請(qǐng)求的處理過程中, 用類似struct 這樣的結(jié)構(gòu)體把一些關(guān)鍵的信息保存起來的結(jié)構(gòu)體, 稱為上下文上下文是針對(duì)一個(gè)請(qǐng)求 一個(gè)模塊而言的, 因而他是低耦合的
  • 使用方法
    • 兩個(gè)宏:
      • ngx_http_get_module_ctx
      • ngx_http_set_ctx
    • 一般的調(diào)用方式是:



      可以看到這里先設(shè)置了上下文,然后后面就可以獲取它并進(jìn)行使用

    • HTTP 框架維護(hù)上下文結(jié)構(gòu)的方式
      • 類似于ngx_http_conf_ctx_t 的 3 個(gè)數(shù)組成員, HTTP 框架 使用 ctx 數(shù)組 保存所有 HTTP 模塊上下文結(jié)構(gòu)體的指針

struct ngx_http_request_s {
...
void ** ctx;
...
}
```
- ngx_http_get_module_ctx 和 ngx_http_set_ctx 的原理就是去獲取或設(shè)置 ctx 數(shù)組中相應(yīng)的 HTTP 模塊的指針

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,002評(píng)論 6 542
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,400評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,136評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,714評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,452評(píng)論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,818評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,812評(píng)論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,997評(píng)論 0 290
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,552評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,292評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,510評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,035評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,721評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,121評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,429評(píng)論 1 294
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,235評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,480評(píng)論 2 379

推薦閱讀更多精彩內(nèi)容

  • 框架代碼分析 核心模塊 啟動(dòng)過程(main) 1、全局ngx_cycle_t對(duì)象 1、ngx_init_cycle...
    AKEEM閱讀 1,114評(píng)論 1 0
  • 本文系轉(zhuǎn)載》》》》》》》》》》》》》》》》 編者按:高可用架構(gòu)分享及傳播在架構(gòu)領(lǐng)域具有典型意義的文章,本文由陳科在...
    demop閱讀 8,098評(píng)論 0 7
  • 前言 Nginx是當(dāng)前最流行的HTTP Server之一,根據(jù)W3Techs的統(tǒng)計(jì),目前世界排名(根據(jù)Alexa)...
    GarfieldEr007閱讀 5,346評(píng)論 4 22
  • 第一章 Nginx簡(jiǎn)介 Nginx是什么 沒有聽過Nginx?那么一定聽過它的“同行”Apache吧!Ngi...
    JokerW閱讀 32,740評(píng)論 24 1,002
  • 編寫HTTP模塊 幾個(gè)重要組成部分ngx_command_t 數(shù)組對(duì)于我們?cè)趎ginx.conf 中編寫的配置項(xiàng) ...
    Spike_3154閱讀 2,524評(píng)論 0 1