nginx報(bào)錯(cuò)(NGINX報(bào)錯(cuò)提示502)
2024-06-02
更新時(shí)間:2024-06-02 00:08:32作者:未知
cycle = ngx_init_cycle(&init_cycle):
1、在內(nèi)存池中分配一個(gè)ngx_cycle_t變量,并初始化它的各個(gè)成員。
2、調(diào)用core類型的create_conf,實(shí)際只有一個(gè)ngx_core_module_create_conf函數(shù)----初始化ngx_core_conf_t結(jié)構(gòu)(存放core_module支持的指令),保存在ngx_cycle->conf_ctx數(shù)組中。可以說,此時(shí),ngx_cycle->conf_ctx數(shù)組中只有一個(gè)ngx_core_conf_t結(jié)構(gòu)。
3、初始化ngx_conf_t結(jié)構(gòu)。
4、ngx_conf_parse 解析配置文件,把結(jié)果保存在模塊對(duì)應(yīng)的ngx_conf里面。
5、調(diào)用core類型的init_conf,實(shí)際只有一個(gè)ngx_core_module_init_conf函數(shù)(初始化對(duì)應(yīng)的ngx_core_conf_t函數(shù))。為什么要init,都已經(jīng)解析配置文件了,應(yīng)該在這之前初始化呀--如果值為-1,表明沒有設(shè)置,初始化默認(rèn)值!
6、ngx_open_listening_sockets:遍歷listening數(shù)組并打開所有偵聽sockets(socket()->setsockopt()->bind()->listen())。
7、調(diào)用所有模塊的init_module(實(shí)際上只有ngx_event_core_module模塊定義了該callback,即只有ngx_event_module_init()被調(diào)用)。
ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename):
函數(shù)的作用就是循環(huán)不停的從配置文件中讀取指令,然后進(jìn)行指令處理,直到結(jié)束
1、先分析ngx_core_module的指令及其對(duì)應(yīng)的set函數(shù)。
{ ngx_string("daemon"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
0,
offsetof(ngx_core_conf_t, daemon),
//計(jì)算daemon成員在ngx_core_conf_t結(jié)構(gòu)體里面的偏移
NULL },
ngx_conf_set_flag_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf):里面代碼很清楚,根據(jù)配置指令,設(shè)置模塊conf結(jié)構(gòu)的成員變量。
2、分析ngx_events_modules的指令及其對(duì)應(yīng)的set函數(shù)。只有一條指令:
{ ngx_string("events"),
NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
ngx_events_block,
0,
0,
NULL },
1、ngx_events_module編號(hào)為3,于是ngx_cycle->conf_ctx指向的void*數(shù)組第3號(hào)槽位指向一個(gè)void*指針,這個(gè)指針又指向一個(gè)void*數(shù)組(個(gè)數(shù)==事件類型模塊的個(gè)數(shù),Linux平臺(tái)編譯之后,只有兩個(gè)ngx_epoll_module事件模型ngx_event_core_module和ngx_epoll_module)。
2、調(diào)用event類型模塊的上下文ngx_event_module_t 的create_conf鉤子,為void*數(shù)組指定槽位創(chuàng)建相應(yīng)的conf結(jié)構(gòu)。
3、更改當(dāng)前cf環(huán)境(NGX_EVENT_MODULE,NGX_EVENT_CONF)解析events{ 塊里面的指令。里面的set函數(shù)都是根據(jù)配置文件設(shè)置ngx_event_conf_t結(jié)構(gòu)體里面的成員變量。
3、分析ngx_http_module的指令及其對(duì)應(yīng)的set函數(shù)。只有一條指令,如下:
{ ngx_string("http"),
NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
ngx_http_block,
0,
0,
NULL },
ngx_init_cycle創(chuàng)建了core module的config,那么http module相關(guān)的config在那里創(chuàng)建呢?http module相關(guān)的config是在ngx_http_block中創(chuàng)建(ngx_http_conf_ctx_t)的,在ngx_http_block中會(huì)創(chuàng)建,初始化,合并config(未完全看懂),以及整個(gè)http handler phase的初始化(還未看)等等。
1、為ngx_cycle->conf_ctx指向的void*數(shù)組創(chuàng)建ngx_http_conf_ctx_t結(jié)構(gòu),并為ngx_http_conf_ctx_t 創(chuàng)建main_conf srv_conf loc_conf三個(gè)void*數(shù)組,數(shù)組大小為http類型模塊的個(gè)數(shù)。
2、遍歷所有的http類型的模塊的上下文ngx_http_module_t,調(diào)用create_main_conf、create_srv_conf、create_loc_conf 分別在ngx_http_conf_ctx_t 的三個(gè)數(shù)組(main_conf srv_conf loc_conf)的對(duì)應(yīng)槽位創(chuàng)建響應(yīng)的結(jié)構(gòu)體變量。
3、遍歷所有的http類型的模塊的上下文ngx_http_module_t, 調(diào)用 preconfiguration 鉤子函數(shù)。
4、解析http塊里面的指令:ngx_conf_parse 未看,當(dāng)前環(huán)境:ctx指向ngx_http_conf_ctx_t,指令類型為NGX_HTTP_MAIN_CONF,模塊類型為:NGX_HTTP_MODULE。
4.1、 遇到http里面的main指令:
if (cmd->type & NGX_DIRECT_CONF) {
conf = ((void **) cf->ctx)[ngx_modules[i]->index]; //ngx_core_conf_t
} else if (cmd->type & NGX_MAIN_CONF) {
//hp: 比如,遇到http/events指令,這里,conf指向的是cf->ctx的第idx個(gè)槽位
conf = &(((void **) cf->ctx)[ngx_modules[i]->index]);
} else if (cf->ctx) {
//否則進(jìn)入二級(jí)模塊處理,比如events/http {里面的指令,都是在這里
//http 里面的main指令,ctx指向于ngx_http_conf_ctx_t
confp = *(void **) ((char *) cf->ctx + cmd->conf); //這里,cmd->conf的作用體現(xiàn)出來了
if (confp) {
//http里面的main指令: conf指向的是對(duì)應(yīng)的ngx_http_core_main_conf_t
conf = confp[ngx_modules[i]->ctx_index];
}
}
比如variables_hash_max_size 指令:
{ ngx_string("variables_hash_max_size"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot, //這里,剛好設(shè)置conf(ngx_http_core_main_conf_t) 的variables_hash_max_size的值。
NGX_HTTP_MAIN_CONF_OFFSET, //這里,conf+NGX_HTTP_MAIN_CONF_OFFSET就是需要設(shè)置的結(jié)構(gòu)體==ngx_http_core_main_conf_t變量地址
offsetof(ngx_http_core_main_conf_t, variables_hash_max_size), //需要設(shè)置結(jié)構(gòu)體中的哪個(gè)成員,成員在結(jié)構(gòu)體中的偏移。
NULL },
總結(jié)出struct ngx_command_s { // 這個(gè)域主要是供nginx解析配置文件時(shí)使用,設(shè)置相關(guān)的數(shù)據(jù)結(jié)構(gòu)
ngx_str_t name;
//命令名稱
ngx_uint_t type;
//命令類型(有幾個(gè)參數(shù)等)
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); //這個(gè)conf指向需要設(shè)置的結(jié)構(gòu)體變量地址
ngx_uint_t conf;
//配置結(jié)構(gòu)體在內(nèi)存的位置,相對(duì)于conf的偏移量,在ngx_conf_handler中使用
ngx_uint_t offset;
//要設(shè)置結(jié)構(gòu)體的哪個(gè)成員,相對(duì)于結(jié)構(gòu)體的偏移量
void *post;
//一些讀取配置時(shí)候的零碎變量,一般為null
};
4.2 遇到 server指令時(shí):
生成一個(gè)新的ngx_http_conf_ctx_t,其中main_conf指向原來的,server_conf和loc_conf創(chuàng)建新的void*數(shù)組。把ngx_http_core_module的server塊配置信息存入 main_conf 中的server 容器里面。更新當(dāng)前環(huán)境。 開始解析server塊里面的指令。
cf->ctx = ctx; //指向新的ngx_http_conf_ctx_t
cf->cmd_type = NGX_HTTP_SRV_CONF;
4.3 遇到server里面的指令:遇到listen 指令時(shí),ngx_conf_handler中,confp指向的新的ngx_http_conf_ctx_t.srv_conf所指向的void*數(shù)組,于是 conf = confp[ngx_modules[i]->ctx_index];指向listen指令對(duì)應(yīng)的模塊(ngx_htt_core_module)的 ngx_http_core_srv_conf_t數(shù)據(jù)結(jié)構(gòu)。
4.4 遇到location指令:生成一個(gè)新的ngx_http_conf_ctx_t,其中main_conf指向原來的,srv_conf指向上一層ngx_http_conf_ctx_t的srv_conf數(shù)組,loc_conf創(chuàng)建新的void*數(shù)組。
ngx_http_core_location 這個(gè)函數(shù)很麻煩,看起來主要是設(shè)置ngx_http_loc_conf_ctx_t里面的name變量。然后遞歸調(diào)用ngx_parse_conf解析location里面的命令。
4.5: 遇到location里面的命令。比如 root,設(shè)置ngx_http_loc_conf_ctx_t里面的root變量。
5、回到ngx_http_block函數(shù)!遍歷每個(gè)http類型的模塊,調(diào)用模塊上下文ngx_http_module_t中的init_main_conf鉤子初始化模塊對(duì)應(yīng)的main_conf配置信息,然后調(diào)用ngx_http_merge_servers。