nginx的配置由一個主配置文件和其餘一些輔助的配置文件構成。這些配置文件均是純文本文件,這些配置文件所有位於nginx安裝目錄下的conf目錄中。html
主配置文件nginx.conf中的內容大概是這樣子的:nginx
#user nobody; worker_processes 1; pid logs/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; location / { root html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
從上面能夠看出:nginx.conf由若干配置項組成,配置項又分爲簡單配置項和塊配置項。正則表達式
簡單配置項由配置項名和配置項值構成。數組
配置項名是一個字符串,能夠用單引號或者雙引號括起來,也能夠不擴。可是若是配置項名包含空格,則必定要括起來。配置項值使用一個或者多個空格或者TAB與配置項名分開,配置項值能夠是數字或者字符串(固然也包括正則表達式)。一個配置項能夠有多個配置項值,多個配置項值之間也由空格或者TAB分隔。簡單配置項的結尾使用分號結束,其基本的語法格式以下:bash
配置項名 配置項值1 配置項值2 ... ;
塊配置項由一個配置項名和一對大括號組成,其結尾不須要再添加分號。塊配置項使用大括號把一系列所屬的配置項所有包含起來,表示大括號內的配置項同時生效;塊配置項也能夠有配置項值,這取決於解析這個配置項的模塊;塊配置項能夠嵌套,內層塊直接繼承外層塊,同一個配置項能夠同時出如今內外層塊配置項中,其優先級也取決於解析該配置項的模塊。app
nginx配置解析的流程基本上是一個遞歸的過程,以下圖所示:函數
在配置解析的入口函數 ngx_conf_parse 中會循環讀取配置文件中的內容,每讀取一行後就解析該配置項。解析的過程當中可能會再次調用該函數完成後續配置項的解析,例如events塊配置項,http塊配置項的解析。spa
對應的源碼:命令行
char * ngx_conf_parse(ngx_conf_t * cf, ngx_str_t * filename) { ... if( filename ){ fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); ... } else if(cf->conf_file->file.fd != NGX_INVALID_FILE){ type = parse_block; } else { type = parse_param; } for( ;; ){ rc = ngx_conf_read_token(cf); if(cf->handler){ ... } rc = ngx_conf_handler(cf, rc); } ... } static ngx_int_t ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last) { for(i = 0; cf->cycle->modules[i]; i++){ cmd = cf->cycle->modules[i]->commands; if(cmd == NULL){ continue; } for( ; cmd->name.len; cmd++ ){ if( name->len != cmd->name.len){ continue; } if(ngx_strcmp(name->data, cmd->name.data) != 0){ continue; } found = 1; ... rc = cmd->set(cf, cmd, conf); } } }
ngx_conf_parse函數支持三種不一樣的解析環境:code
從前面的解析流程能夠看出,首次調用ngx_conf_parse進行配置解析時,類型爲parse_file,當遞歸調用時,ngx_conf_parse的filename參數均設置爲空,即正在進行塊配置項的解析,例如:
static char * ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ... cf->ctx = ctx; cf->module_type = NGX_EVENT_MODULE; cf->cmd_type = NGX_EVENT_CONF; rv = ngx_conf_parse(cf, NULL); ... }
在ngx_conf_handler的校驗過程當中會針對模塊類型、配置項類型、配置項值個數等進行校驗。
if( cf->cycle->modules[i]->type != NGX_CONF_MODULE && cf->cycle->modules[i]->type != cf->module_type ){ continue; }
cf->module_type 初始值設置爲 NGX_CORE_MODULE(在ngx_init_cycle函數中初始化),解析到配置項 http { 的時候,找到ngx_http_module模塊,並調用ngx_http_block處理該配置項。從ngx_http_module模塊的定義能夠看到其類型確實爲NGX_CORE_MODULE。
static ngx_command_t ngx_http_commands[] = { { ngx_string("http"), NGX_MAIN_CONF | NGX_CONF_BLOCK | NGX_CONF_NOARGS, ngx_http_block, 0, 0, NULL }, ngx_null_command }; ngx_module_t ngx_http_module = { NGX_MODULE_V1, &ngx_http_module_ctx, ngx_http_commands, NGX_CORE_MODULE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NGX_MODULE_P1_PADDING };
在ngx_http_block中將cf->module_type設置爲NGX_HTTP_MODULE,解析http塊配置項中的其餘配置項時,找到對應的http模塊並進行後續處理,而全部http模塊的類型均定義爲NGX_HTTP_MODULE。 這樣,可有效防止配置項被其餘模塊所處理。
if(!(cmd->type & cf->cmd_type)){ continue; }
cmd->type初始值爲NGX_MAIN_CONF,前面提到的ngx_http_module模塊的配置項數組中http配置項的類型包含了NGX_MAIN_CONF。
前面提到每一個配置項名後能夠有多個配置項值,當前配置項值的最大個數定義爲8。代碼中有相關的宏對應。配置項值的個數必須正確才能進行實際的配置項解析。
#define NGX_CONF_MAX_ARGS 8 #define NGX_CONF_NOARGS 0x00000001 //無配置項值 #define NGX_CONF_TAKE1 0x00000002 //接受1個配置項值 #define NGX_CONF_TAKE2 0x00000004 //接受2個配置項值 #define NGX_CONF_TAKE3 0x00000008 //接受3個配置項值 #define NGX_CONF_TAKE4 0x00000010 //接受4個配置項值 #define NGX_CONF_TAKE5 0x00000020 //接受5個配置項值 #define NGX_CONF_TAKE6 0x00000040 //接受6個配置項值 #define NGX_CONF_TAKE7 0x00000080 //接受7個配置項值 #define NGX_CONF_BLOCK 0x00000100 //接受塊配置項 #define NGX_CONF_FLAG 0x00000200 //接受配置項值爲on或者off #define NGX_CONF_ANY 0x00000400 //接受任意的配置項值 #define NGX_CONF_1MORE 0x00000800 //至少1個配置項值 #define NGX_CONF_2MORE 0x00001000 //至少2個配置項值 #define NGX_CONF_MULTI 0x00000000 //接受多個配置項值 個數不定 //接受1個或2個配置項值 #define NGX_CONF_TAKE12 (NGX_CONF_TAKE1|NGX_CONF_TAKE2) //接受1個或3個配置項值 #define NGX_CONF_TAKE13 (NGX_CONF_TAKE1|NGX_CONF_TAKE3) //接受2個或3個配置項值 #define NGX_CONF_TAKE23 (NGX_CONF_TAKE2|NGX_CONF_TAKE2) //接受1個或2個或3個配置項值 #define NGX_CONF_TAKE123 (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3) //接受1個或2個或4個配置項值 #define NGX_CONF_TAKE1234 (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3|NGX_CONF_TAKE4)
參考:
《深刻理解nginx》
《nginx開發從入門到精通》