nginx變量使用方法詳解(5)

前面在 (二) 中我們已經(jīng)了解到變量值容器的生命期是與請(qǐng)求綁定的,但是我當(dāng)時(shí)有意避開了“請(qǐng)求”的正式定義。大家應(yīng)當(dāng)一直默認(rèn)這里的“請(qǐng)求”都是指客戶端發(fā)起的 HTTP 請(qǐng)求。其實(shí)在 Nginx 世界里有兩種類型的“請(qǐng)求”,一種叫做“主請(qǐng)求”(main request),而另一種則叫做“子請(qǐng)求”(subrequest)。我們先來介紹一下它們。 所謂“主請(qǐng)求”,就是由 HTTP 客戶端從 Nginx 外部發(fā)起的請(qǐng)求。

成都創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),南開企業(yè)網(wǎng)站建設(shè),南開品牌網(wǎng)站建設(shè),網(wǎng)站定制,南開網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷,網(wǎng)絡(luò)優(yōu)化,南開網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。

我們前面見到的所有例子都只涉及到“主請(qǐng)求”,包括 (二) 中那兩個(gè)使用 echo_exec 和 rewrite 指令發(fā)起“內(nèi)部跳轉(zhuǎn)”的例子。 而“子請(qǐng)求”則是由 Nginx 正在處理的請(qǐng)求在 Nginx 內(nèi)部發(fā)起的一種級(jí)聯(lián)請(qǐng)求。“子請(qǐng)求”在外觀上很像 HTTP 請(qǐng)求,但實(shí)現(xiàn)上卻和 HTTP 協(xié)議乃至網(wǎng)絡(luò)通信一點(diǎn)兒關(guān)系都沒有。它是 Nginx 內(nèi)部的一種抽象調(diào)用,目的是為了方便用戶把“主請(qǐng)求”的任務(wù)分解為多個(gè)較小粒度的“內(nèi)部請(qǐng)求”,并發(fā)或串行地訪問多個(gè) location 接口,然后由這些 location 接口通力協(xié)作,共同完成整個(gè)“主請(qǐng)求”。當(dāng)然,“子請(qǐng)求”的概念是相對(duì)的,任何一個(gè)“子請(qǐng)求”也可以再發(fā)起更多的“子子請(qǐng)求”,甚至可以玩遞歸調(diào)用(即自己調(diào)用自己)。當(dāng)一個(gè)請(qǐng)求發(fā)起一個(gè)“子請(qǐng)求”的時(shí)候,按照 Nginx 的術(shù)語,習(xí)慣把前者稱為后者的“父請(qǐng)求”(parent request)。值得一提的是,Apache 服務(wù)器中其實(shí)也有“子請(qǐng)求”的概念,所以來自 Apache 世界的讀者對(duì)此應(yīng)當(dāng)不會(huì)感到陌生。 下面就來看一個(gè)使用了“子請(qǐng)求”的例子:

location /main { echo_location /foo; echo_location /bar; } location /foo { echo foo; } location /bar { echo bar; } 這里在 location /main 中,通過第三方 ngx_echo 模塊的 echo_location 指令分別發(fā)起到 /foo 和 /bar 這兩個(gè)接口的 GET 類型的“子請(qǐng)求”。由 echo_location 發(fā)起的“子請(qǐng)求”,其執(zhí)行是按照配置書寫的順序串行處理的,即只有當(dāng) /foo 請(qǐng)求處理完畢之后,才會(huì)接著處理 /bar 請(qǐng)求。這兩個(gè)“子請(qǐng)求”的輸出會(huì)按執(zhí)行順序拼接起來,作為 /main 接口的最終輸出:

$ curl \'http://localhost:8080/main\' foo bar 我們看到,“子請(qǐng)求”方式的通信是在同一個(gè)虛擬主機(jī)內(nèi)部進(jìn)行的,所以 Nginx 核心在實(shí)現(xiàn)“子請(qǐng)求”的時(shí)候,就只調(diào)用了若干個(gè) C 函數(shù),完全不涉及任何網(wǎng)絡(luò)或者 UNIX 套接字(socket)通信。我們由此可以看出“子請(qǐng)求”的執(zhí)行效率是極高的。 回到先前對(duì) Nginx 變量值容器的生命期的討論,我們現(xiàn)在依舊可以說,它們的生命期是與當(dāng)前請(qǐng)求相關(guān)聯(lián)的。每個(gè)請(qǐng)求都有所有變量值容器的獨(dú)立副本,只不過當(dāng)前請(qǐng)求既可以是“主請(qǐng)求”,也可以是“子請(qǐng)求”。即便是父子請(qǐng)求之間,同名變量一般也不會(huì)相互干擾。讓我們來通過一個(gè)小實(shí)驗(yàn)證明一下這個(gè)說法:

location /main { set $var main; echo_location /foo; echo_location /bar; echo "main: $var"; } location /foo { set $var foo; echo "foo: $var"; } location /bar { set $var bar; echo "bar: $var"; } 在這個(gè)例子中,我們分別在 /main,/foo 和 /bar 這三個(gè) location 配置塊中為同一名字的變量,$var,分別設(shè)置了不同的值并予以輸出。特別地,我們?cè)?/main 接口中,故意在調(diào)用過 /foo 和 /bar 這兩個(gè)“子請(qǐng)求”之后,再輸出它自己的 $var 變量的值。請(qǐng)求 /main 接口的結(jié)果是這樣的:

$ curl \'http://localhost:8080/main\' foo: foo bar: bar main: main 顯然,/foo 和 /bar 這兩個(gè)“子請(qǐng)求”在處理過程中對(duì)變量 $var 各自所做的修改都絲毫沒有影響到“主請(qǐng)求” /main. 于是這成功印證了“主請(qǐng)求”以及各個(gè)“子請(qǐng)求”都擁有不同的變量 $var 的值容器副本。 不幸的是,一些 Nginx 模塊發(fā)起的“子請(qǐng)求”卻會(huì)自動(dòng)共享其“父請(qǐng)求”的變量值容器,比如第三方模塊 ngx_auth_request. 下面是一個(gè)例子:

location /main { set $var main; auth_request /sub; echo "main: $var"; } location /sub { set $var sub; echo "sub: $var"; } 這里我們?cè)?/main 接口中先為 $var 變量賦初值 main,然后使用 ngx_auth_request 模塊提供的配置指令 auth_request,發(fā)起一個(gè)到 /sub 接口的“子請(qǐng)求”,最后利用 echo 指令輸出變量 $var 的值。而我們?cè)?/sub 接口中則故意把 $var 變量的值改寫成 sub. 訪問 /main 接口的結(jié)果如下:

$ curl \'http://localhost:8080/main\' main: sub 我們看到,/sub 接口對(duì) $var 變量值的修改影響到了主請(qǐng)求 /main. 所以 ngx_auth_request 模塊發(fā)起的“子請(qǐng)求”確實(shí)是與其“父請(qǐng)求”共享一套 Nginx 變量的值容器。 對(duì)于上面這個(gè)例子,相信有讀者會(huì)問:“為什么‘子請(qǐng)求’ /sub 的輸出沒有出現(xiàn)在最終的輸出里呢?”答案很簡(jiǎn)單,那就是因?yàn)?auth_request 指令會(huì)自動(dòng)忽略“子請(qǐng)求”的響應(yīng)體,而只檢查“子請(qǐng)求”的響應(yīng)狀態(tài)碼。當(dāng)狀態(tài)碼是 2XX 的時(shí)候,auth_request 指令會(huì)忽略“子請(qǐng)求”而讓 Nginx 繼續(xù)處理當(dāng)前的請(qǐng)求,否則它就會(huì)立即中斷當(dāng)前(主)請(qǐng)求的執(zhí)行,返回相應(yīng)的出錯(cuò)頁。在我們的例子中,/sub “子請(qǐng)求”只是使用 echo 指令作了一些輸出,所以隱式地返回了指示正常的 200 狀態(tài)碼。 如 ngx_auth_request 模塊這樣父子請(qǐng)求共享一套 Nginx 變量的行為,雖然可以讓父子請(qǐng)求之間的數(shù)據(jù)雙向傳遞變得極為容易,但是對(duì)于足夠復(fù)雜的配置,卻也經(jīng)常導(dǎo)致不少難于調(diào)試的詭異 bug. 因?yàn)橛脩魰r(shí)常不知道“父請(qǐng)求”的某個(gè) Nginx 變量的值,其實(shí)已經(jīng)在它的某個(gè)“子請(qǐng)求”中被意外修改了。諸如此類的因共享而導(dǎo)致的不好的“副作用”,讓包括 ngx_echo,ngx_lua,以及 ngx_srcache 在內(nèi)的許多第三方模塊都選擇了禁用父子請(qǐng)求間的變量共享。

文章名稱:nginx變量使用方法詳解(5)
地址分享:http://www.muchs.cn/article30/cjjjpo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站、企業(yè)網(wǎng)站制作、品牌網(wǎng)站設(shè)計(jì)、網(wǎng)站導(dǎo)航、營(yíng)銷型網(wǎng)站建設(shè)網(wǎng)站內(nèi)鏈

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設(shè)