Nginx配置檔案解析之三

2021-08-26 10:37:02 字數 4430 閱讀 5972

通過前面的分析,location部分的解析跟http和server是同樣的道理。

來看下面兩句:

ctx是在解析該location時生成的ngx_http_conf_ctx_t,自然它的main_conf和srv_conf都會繼承上層,而在本層重新設定loc_conf,這裡我們看到,在location的解析中

ngx_http_core_loc_conf_t結構(即clcf)的loc_conf成員會儲存所有其他module的location配置,用到的時候引用方便。

這裡還有幾個要說一下的:

clcf->exact_match:類似 location = / {},所謂準確匹配。

clcf->noregex:沒有正則,但不要求準確匹配,如/usr可以跟/usr/local算匹配

clcf->named:以』@』開頭的,如location @test {}

clcf->noname:nginx會把if 指令配置也看做乙個location,即noname型別。

location中出現『~』的,就認為是有正則的配置了,就會呼叫ngx_http_core_regex_location

來處理,注意一點的是,這個函式的第三個引數是大小寫標記,一般「~」是忽略大小寫處理的,而「~*」是要考慮大小寫的。

函式中會呼叫ngx_http_regex_compile來對正規表示式做處理,使用是pcre庫,具體的介面和原理,大家可以去pcre官網去找一下。這個函式的乙個重點在於它會把正則中出現的$1,$2…等,提取出代表的字串作為乙個」 引數」,放到全域性的參數列中,供後面使用。關於nginx中的變數和指令碼特性,會在配置解析這塊分析完之後,做專門分析。

繼續看:

這裡是拿到上層的location(若有的話),來驗證內嵌的location配置語法是否合法。

如果上層的location是準確配置的(即exact_match)或者帶「@」的(named),那麼不允許內嵌location,還有內嵌的location不能為named,即帶「@」的。如果這些檢查通過,那麼還要求內嵌的location 路徑要跟上層的路徑有公共字首。

如:location /usr/ {

location /usr/local/ {

來看這個函式:ngx_http_add_location

它涉及乙個ngx_http_location_queue_t的結構, 即lq。乙個location的配置,即**裡的clcf會通過這個結構儲存,如果當前的location沒有巢狀,那麼它就是exact的,放在這個結構的exact,巢狀的放到結構的inclusive中。

看這一句:ngx_queue_insert_tail(*locations,&lq->queue);

大家應該明白它的意圖,那就是內嵌在乙個location中的各個location配置,會組成乙個雙向queue,掛在上層的配置結構locations成員裡(即queue頭),如pclcf->locations。

從server配置的角度看,每遇到乙個location,都會建立乙個雙向queue,沒有內嵌的,也就只有它自己罷了。

location部分就做了這些事情,因為整個處理是乙個遞迴過程,所以我們看看當解析完location,回到http處理時,還會做些什麼。

回到函式ngx_http_block,我們前面說過了,當ngx_http_block中ngx_conf_parse返回的時候,意味著下層的server和locatio都已解析整理完畢了。好了,我們把最後的任務拿出來看下:

就是這樣乙個for迴圈,那麼它到底做了什麼?

cscfp是http block中各個server的配置資訊,以陣列的形式儲存在main_conf的servers成員裡。

這一句:clcf =cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];

我們拿到http_core_module在各個srv_conf,即cscfp[s],並從中獲得loc_conf,即clcf,這兩個結構作為ngx_http_init_locations的第二和第三個引數傳入,有一點需要記住的是,clcf中的locations成員(即queue頭),包含了該server下的所有location。

我們進入ngx_http_init_locations函式。

首先對locationqueue進行排序,即ngx_queue_sort,排序的規則可以讀一下ngx_http_cmp_locations函式。

排列完成之後的順序大致為:regex,named,noname等,而且每個相同型別可能含有多個,如r1,r2,r3,n1,n2,n3,nm1,nm2,這樣可以把相同型別的歸為一類,**中則通過regex和r來記錄regex型別的開始位置和個數,name和n記錄named型別的起始位置和個數。型別分離時,使用ngx_queue_split按照從後往前的方式,先分離noname(沒有像後面兩個那樣集中管理),在分離named(儲存到cscf->named_locations),最後分離regex(儲存到pclcf->regex_locations= clcfp),分離這些另類之後,我們處理那些普通的location,普通的location大家應該知道是指的哪些,nginx稱為static location。

從ngx_http_init_locations返回後,我們看到接下來的處理,之前我們已經把乙個server下面的locations做了處理,包括切割和分類,下面的ngx_http_init_static_location_trees函式就會將那些普通的location,即staticlocation,進行樹化(一種三叉樹)處理,之所以要做這樣的處理,是為了在處理http請求時能高效的搜尋的匹配的location配置。

我們知道的一點是,這些staticlocation放在了乙個queue中,裡面每個節點可能還會掛有內嵌的location,所以ngx_http_init_static_location_trees會在他們內嵌的location裡被遞迴呼叫,所以我們明白了無內嵌location的建樹過程,基本上就知道是個什麼結果是個什麼樣子了。

在處理中,會先呼叫ngx_http_join_exact_locations函式來做一些預處理,主要是去重,去重的標準,**裡體現的很明確,這裡就不說了。

接下來呼叫ngx_http_create_locations_list,這個函式的作用是這樣的:

在開始的這個locationqueue中,有一些是有相同路徑字首的,自然他們在排序的時候也是會挨在一起的,ngx_http_create_locations_list會將跟某個location有相同字首的location,從原來的queue上取下,掛在該location的list成員下,這樣在主queue上的location都是具有相互不同name的location了。舉個例子:

主鏈:/a ->/ab -> /abc-> /b ->/bc -> /bcd-> /c -> /cd-> /cde

處理之後:/a ->/b -> /c

/ab /bc/cd

/abc /bcd/cde

好了最後我們呼叫ngx_http_create_locations_tree來完成這個三叉樹的建立。

主要說下大概的過程吧,像這種演算法的分析,講起來會很囉嗦,這裡只是提個綱,大家還是得自己看。

2.左邊的部分,遞迴呼叫ngx_http_create_locations_tree,生成left樹

3.右邊的部分,遞迴呼叫ngx_http_create_locations_tree,生成right樹

4.中間位置的location,通過它的list,通過遞迴呼叫ngx_http_create_locations_tree,生成tree樹(可以認為是中樹)。

大家可以想象一下,這樣的乙個過程結束時候的情景,呵呵!差不多就是這樣了。

bs: 本人水平有限,分析中可能有一些理解不到位的地方,還請大家多指點!

Nginx配置檔案解析

nginx配置檔案解析 nginx配置檔案預設在 usr local nginx conf nginx.conf,配置檔案包括 全域性 event http server設定 event主要設定nginx的工作模式,http提供web功能 server用來設定虛擬主機,server必須位於http內...

nginx配置檔案解析

nginx為微核心加可擴充套件模組。自身模組有core event http mail等核心模組。開發者可以基於這些核心模組開發滿足自身業務需求的模組,主要是http模組。nginx的配置項的資料結構 struct ngx cycle sconf ctx是乙個指標陣列,陣列一共有ngx max mo...

nginx配置檔案解析

nginx 監聽原理 先監聽埠 再配置網域名稱 匹配到就訪問local 否則 沒有匹配到網域名稱就預設訪問第乙個監聽埠的local位址 定義錯誤頁面,如果是500錯誤,則把站點根目錄下的50x.html返回給使用者 location 50x.html nginx 監聽原理 先監聽埠 再配置網域名稱 ...