Nginx學(xué)習(xí):代理模塊(二)緩存與錯誤處理在基本的配置學(xué)習(xí)之后,其實大部分的業(yè)務(wù)場景就已經(jīng)夠用了,沒錯,就那一個 proxy_pass 指令,真的就夠了。但是,對于許多更復(fù)雜的業(yè)務(wù)場景來說,Nginx 的代理模塊還是提供了更多的功能,做為每個想成為架構(gòu)師的碼農(nóng)來說,這一部分不說多精通,至少也都得有些了解。今天學(xué)習(xí)的代理模塊緩存與錯誤處理和 FastCGI 模塊非常類似,很多內(nèi)容我們照搬之前的測試方式就可以了。 今天的配置指令大部分都是可以在 http、server、location 下配置的,僅有 proxy_cache_path 是只能在 http 模塊下配置的,我們馬上就會看到。 Proxy緩存代理的緩存也是在獲得代理的響應(yīng)之后,對響應(yīng)的結(jié)果進行緩存,也可以進行不同的配置來實現(xiàn)是否需要走緩存,同樣地,清理緩存的指令也是商業(yè)版的,如果需要相應(yīng)的功能,需要第三方的插件。 還是先來看相關(guān)的配置指令,最后再一起進行簡單地測試。 proxy_cache_path設(shè)置緩存的路徑和其他參數(shù)。
沒有默認(rèn)值,需要配置在 http 模塊下配置。緩存數(shù)據(jù)存儲在文件中。緩存中的文件名是對緩存鍵應(yīng)用 MD5 函數(shù)的結(jié)果。 levels 參數(shù)定義緩存的層次級別:從 1 到 3,每個級別接受值 1 或 2。 緩存的響應(yīng)會首先寫入臨時文件,然后重命名該文件。從 0.8.9 版本開始,臨時文件和緩存可以放在不同的文件系統(tǒng)上。但是,請注意,在這種情況下,文件是跨兩個文件系統(tǒng)復(fù)制的,而不是廉價的重命名操作。因此,建議對于任何給定位置,緩存和保存臨時文件的目錄都放在同一個文件系統(tǒng)上。臨時文件的目錄是根據(jù) use_temp_path 參數(shù) (1.7.10) 設(shè)置的。如果省略此參數(shù)或?qū)⑵湓O(shè)置為值 on,則將使用 proxy_temp_path 指令為給定位置設(shè)置的目錄。如果該值設(shè)置為 off,則臨時文件將直接放在緩存目錄中。 此外,所有活動密鑰和有關(guān)數(shù)據(jù)的信息都存儲在共享內(nèi)存區(qū)域中,其名稱和大小由 keys_zone 參數(shù)配置。一兆字節(jié)的區(qū)域可以存儲大約 8000 個密鑰。 在 inactive 參數(shù)指定的時間內(nèi)未訪問的緩存數(shù)據(jù)將從緩存中刪除,無論其新鮮度如何。默認(rèn)情況下,非活動設(shè)置為 10 分鐘。特殊的“緩存管理器”進程監(jiān)控由 max_size 參數(shù)設(shè)置的最大緩存大小,以及由 min_free (1.19.1) 參數(shù)設(shè)置的帶緩存文件系統(tǒng)上的最小可用空間量。當(dāng)超出大小或沒有足夠的可用空間時,它會刪除最近最少使用的數(shù)據(jù)。數(shù)據(jù)在 manager_files、manager_threshold 和 manager_sleep 參數(shù) (1.11.5) 配置的迭代中被刪除。在一次迭代中,最多刪除 manager_files 個項目(默認(rèn)為 100)。一次迭代的持續(xù)時間受 manager_threshold 參數(shù)的限制(默認(rèn)為 200 毫秒)。在迭代之間,由 manager_sleep 參數(shù)配置的暫停(默認(rèn)為 50 毫秒)。 啟動后一分鐘,特殊的“緩存加載器”進程被激活。它將有關(guān)存儲在文件系統(tǒng)上的先前緩存數(shù)據(jù)的信息加載到緩存區(qū)域中。加載也是在迭代中完成的。在一次迭代中,最多加載 loader_files 個項目(默認(rèn)情況下,100 個)。此外,一次迭代的持續(xù)時間受 loader_threshold 參數(shù)的限制(默認(rèn)為 200 毫秒)。在迭代之間,由 loader_sleep 參數(shù)配置的暫停(默認(rèn)為 50 毫秒)。 proxy_cache定義用于緩存的共享內(nèi)存區(qū)域。
默認(rèn)值是 off ,其實就是開啟代理緩存功能的開關(guān)。同一個區(qū)域可以在多個地方使用,參數(shù)值可以包含變量 (1.7.9)。 off 參數(shù)禁用從先前配置級別繼承的緩存。 proxy_cache_background_update允許啟動后臺子請求以更新過期的緩存項,同時將過時的緩存響應(yīng)返回給客戶端。
默認(rèn)值是 off ,請注意,有必要在更新時允許使用陳舊的緩存響應(yīng)。 proxy_cache_bypass定義不從緩存中獲取響應(yīng)的條件。
沒有默認(rèn)值,如果字符串參數(shù)中至少有一個值不為空且不等于“0”,則不會從緩存中獲取響應(yīng):
上面的意思就是 cookie 中有 nocache 字段 ,或者 Get 請求參數(shù)中有 nocache 字段和 comment 字段,并且這些字段都不為空;或者請求頭有 pragma 或 authorization 字段,那么這個請求就不會走緩存。它可以與 proxy_no_cache 指令一起使用。 proxy_cache_convert_head啟用或禁用將“HEAD”方法轉(zhuǎn)換為“GET”以進行緩存。
默認(rèn)值是 on ,禁用轉(zhuǎn)換時,應(yīng)將緩存鍵配置為包含 proxy_cache_key定義一個用于緩存的鍵。
默認(rèn)值是
默認(rèn)情況下,它更接近于下面這個字符串。
另外,如果有特殊的需要,比如說要緩存 Post 之類的修改型的請求,則應(yīng)該把 proxy_cache_lock啟用后,一次只允許一個請求通過將請求傳遞給代理服務(wù)器來填充根據(jù) proxy_cache_key 指令標(biāo)識的新緩存元素。
默認(rèn) off ,相同緩存元素的其他請求要么等待響應(yīng)出現(xiàn)在緩存中,要么等待釋放該元素的緩存鎖,直到 proxy_cache_lock_timeout 指令設(shè)置的時間。 就是在緩存失效時,如果有多個請求過來,那么只能有一個請求可以去進行緩存操作,解決緩存擊穿的問題。關(guān)于緩存擊穿的問題,如果大家不記得了,可以去 Redis 系列的文章中查看哦。Redis進階:緩存穿透、擊穿與雪崩https://mp.weixin.qq.com/s/298VajkPwGRlTQGxRtPI8g proxy_cache_lock_age如果傳遞給代理服務(wù)器以填充新緩存元素的最后一個請求在指定時間內(nèi)沒有完成,則可以將另一個請求傳遞給代理服務(wù)器。
默認(rèn) 5s 。同樣是緩存過期時,如果一個請求在更新時超時了,那么其它請求就直接傳遞到代理服務(wù)器。 proxy_cache_lock_timeout為 proxy_cache_lock 設(shè)置超時。
默認(rèn)值是 5s ,當(dāng)時間到期時,請求將被傳遞到代理服務(wù)器,但是,響應(yīng)不會被緩存。在 1.7.8 之前,可以緩存響應(yīng)。 proxy_cache_max_range_offset為字節(jié)范圍請求設(shè)置字節(jié)偏移量。
沒有默認(rèn)值,如果范圍超出偏移量,范圍請求將被傳遞到代理服務(wù)器,并且響應(yīng)不會被緩存。沒有測,也不知道咋測,有了解的小伙伴記得留言哦。 proxy_cache_methods如果此指令中列出了客戶端請求方法,則響應(yīng)將被緩存。
“GET”和“HEAD”方法總是添加到列表中,但建議明確指定它們。另請參見 proxy_no_cache 指令。 比如說默認(rèn)情況下,POST 請求是不會被緩存的,如果想要緩存 POST 或者 PUT、DELETE 之類的請求,就需要在這里配置。同時要注意,上面的 proxy_cache_key 配置最好也要加上 proxy_cache_min_uses設(shè)置將緩存響應(yīng)的請求數(shù)。
默認(rèn)值是 1 ,就是只要有一條請求來了,就緩存,一般不用動它。 proxy_cache_purge定義將請求視為緩存清除請求的條件。
沒有默認(rèn)值,如果字符串參數(shù)的至少一個值不為空且不等于“0”,則刪除具有相應(yīng)緩存鍵的緩存條目。返回 204(No Content)響應(yīng)表示操作成功的結(jié)果。 如果清除請求的緩存鍵以星號(“*”)結(jié)尾,則所有與通配符鍵匹配的緩存條目都將從緩存中刪除。但是,這些條目將保留在磁盤上,直到它們因不活動而被刪除,或者被緩存清除器 (1.7.12) 處理,或者客戶端嘗試訪問它們。 商業(yè)版的才提供,不多說了,大家可以使用開源的第三方庫。 proxy_cache_revalidate用帶有“If-Modified-Since”和“If-None-Match”標(biāo)頭字段的條件請求啟用過期緩存項的重新驗證。
默認(rèn)值是 off ,通過請求頭中的 HTTP 緩存相關(guān)字段來做為緩存的更新依據(jù),需要我們 PHP 代碼中添加響應(yīng)頭及處理。 proxy_cache_use_stale確定在哪些情況下可以在與代理服務(wù)器通信期間使用過時的緩存響應(yīng)。
該指令的參數(shù)與 proxy_next_upstream 指令的參數(shù)相匹配。 如果無法選擇代理服務(wù)器來處理請求,則錯誤參數(shù)還允許使用過時的緩存響應(yīng)。此外,如果當(dāng)前正在更新,更新參數(shù)允許使用陳舊的緩存響應(yīng)。這允許在更新緩存數(shù)據(jù)時最小化對代理服務(wù)器的訪問次數(shù)。在響應(yīng)過時 (1.11.10) 后的指定秒數(shù)內(nèi),也可以直接在響應(yīng)標(biāo)頭中啟用使用過時的緩存響應(yīng)。這比使用指令參數(shù)的優(yōu)先級低。
為了在填充新緩存元素時最小化對代理服務(wù)器的訪問次數(shù),可以使用 proxy_cache_lock 指令。 和 FastCGI 相關(guān)的配置功能也是類似的,當(dāng)使用服務(wù)器組做負(fù)載均衡時,如果某一個后端服務(wù)器出現(xiàn)問題了,比如報 500 錯誤了,那么在這里加上 http_500 之后,就會將請求轉(zhuǎn)移到下一個后端服務(wù)器上。 proxy_cache_valid為不同的響應(yīng)代碼設(shè)置緩存時間。
為代碼為 200 和 302 的響應(yīng)設(shè)置 10 分鐘的緩存時間,為代碼為 404 的響應(yīng)設(shè)置 1 分鐘的緩存時間。 如果只指定緩存時間 ,則只有 200, 301, 和 302 的響應(yīng)會被緩存,此外,可以指定 any 參數(shù)來緩存任何響應(yīng) 緩存的參數(shù)也可以直接在響應(yīng)頭中設(shè)置。這比使用指令設(shè)置緩存時間具有更高的優(yōu)先級。
可以使用 proxy_ignore_headers 指令禁用對這些響應(yīng)頭字段中的一個或多個的處理。 proxy_no_cache定義不將響應(yīng)保存到緩存的條件。
如果字符串參數(shù)中至少有一個值不為空且不等于“0”,則不會保存響應(yīng)??梢耘c proxy_cache_bypass 指令一起使用。 Proxy 緩存測試好了,上面的配置指令都看完了,那么咱們就來挑一些進行簡單地測試。為了測試方便,咱們直接使用 PHP 文件來進行測試,因為可以方便地返回隨機數(shù)。
代碼很簡單吧,就是打印了一個隨機數(shù)。另外我們還根據(jù)不同的 GET 參數(shù) code ,返回不同的響應(yīng)狀態(tài)碼,比如我們要返回 500 狀態(tài)碼,就直接加上一個 接下來就簡單配置幾個緩存參數(shù)吧。
注意 proxy_cache_path 是要在 http 下配置的哦,不能在 server 或 location 下面配置。 然后我們就簡單配置了 proxy_cache、proxy_cache_bypass 和 proxy_cache_valid 這三個指令。其中 proxy_cache_bypass 指定如果有 GET 參數(shù) nocache ,就不走緩存;proxy_cache_valid 則分別指定 200 狀態(tài)碼時緩存 3s ,201 狀態(tài)碼時緩存 10s 。
直接使用 CURL 進行測試,加上
默認(rèn)情況下是 200 狀態(tài)碼,因此在三秒內(nèi)多次發(fā)送,返回的隨機數(shù)會是一樣的。三秒后隨機數(shù)才會更新,我們也可以加上 nocache 參數(shù),不走緩存,這樣每次都會走后端的代理請求。
最后,大家還可以加上 code 參數(shù),測試一下 201 是不是會緩存 10s 。
其它的測試大家可以自己試下哦,篇幅有限,這里就不一一測試了。用好緩存可以極大地提高我們的運行效率,緩存讓請求不需要通過代理轉(zhuǎn)發(fā)直接就在第一層 Nginx 就進行處理了。 關(guān)于緩存文件的查看,大家直接在 Nginx 程序運行目錄下的 proxycache 目錄下就可以看到了,內(nèi)容和 FastCGI 生成的緩存文件內(nèi)容是一樣的。 Proxy錯誤處理還是熟悉的配方和熟悉的味道,這里的錯誤處理最主要的就是對于服務(wù)器組來說,當(dāng)某一個后端服務(wù)出現(xiàn)問題時,代理模塊將如何處理。另外就是如果只有一個后端代理,那么錯誤是由 Nginx 來處理還是讓后端來進行處理。這里和 FastCGI 部分也沒什么區(qū)別,咱們邊看指令,邊簡單演示一下就好。 proxy_next_upstream指定在哪些情況下應(yīng)將請求傳遞給下一個服務(wù)器。
默認(rèn)值 error timeout ,參數(shù)的意義是:
應(yīng)該記住,只有在尚未向客戶端發(fā)送任何內(nèi)容的情況下,才有可能將請求傳遞給下一個服務(wù)器。也就是說,如果在傳輸響應(yīng)的過程中發(fā)生錯誤或超時,則無法解決此問題。 該指令還定義了與服務(wù)器通信的不成功嘗試。錯誤、超時和 invalid_header 的情況總是被認(rèn)為是不成功的嘗試,即使它們沒有在指令中指定。 http_500、http_502、http_503、http_504 和 http_429 的情況僅在指令中指定時才被視為不成功嘗試。 http_403 和 http_404 的情況永遠(yuǎn)不會被認(rèn)為是不成功的嘗試。 將請求傳遞到下一個服務(wù)器可能會受到嘗試次數(shù)和時間的限制,也就是后面兩個配置的內(nèi)容,咱們先來測試這個配置指令的效果。 首先我們在 89 這臺服務(wù)器上寫一個 PHP 文件,直接拋出 500 異常。
然后添加 proxy_next_upstream ,指定 http_500 的處理。
服務(wù)器組還是使用之前的 proxy1 那個服務(wù)器組,不斷地刷新,頁面會一直顯示 88 服務(wù)器上的內(nèi)容。注釋掉 proxy_next_upstream 或者去掉 http_500 這個配置,那么錯誤頁面就會顯示出來。 proxy_next_upstream_timeout限制可以將請求傳遞到下一個服務(wù)器的時間。
默認(rèn)是 0 值,表示關(guān)閉此限制,也就是無限制。 proxy_next_upstream_tries限制將請求傳遞到下一個服務(wù)器的可能嘗試次數(shù)。
默認(rèn)是 0 值,表示關(guān)閉此限制,也就是無限制。 proxy_intercept_errors確定代碼大于或等于 300 的代理響應(yīng)是否應(yīng)傳遞給客戶端或被攔截并重定向到 nginx 以使用 error_page 指令進行處理。
默認(rèn) off ,當(dāng)后端代理報錯時,直接顯示的是后端服務(wù)的錯誤信息,通過這個配置,可以攔截并顯示當(dāng)前的代理服務(wù)器的錯誤信息頁面。
這時訪問的結(jié)果就會是當(dāng)前 Nginx 代理指定的 50x.html 頁面了。
如果打開下面的 proxy_next_upstream 的注釋,它們一起運行會是什么結(jié)果呢?以 proxy_next_upstream 為準(zhǔn),如果所有的服務(wù)器組都有問題呢?最后會到 proxy_intercept_errors ,大家可以自己試試哦。 總結(jié)內(nèi)容看著比較多,但其實這些配置指令我們并不陌生,畢竟之前有過 FastCGI 的學(xué)習(xí)了,還是比較好理解的。主要還是需要大家一起動手測試一下,看看效果是不是和我們想像中的一樣。話又說回來,代理模塊還是有些特有的配置,我們下篇文章就會看到一個,一步一個腳印,繼續(xù)加油吧。 參考文檔: http:///en/docs/http/ngx_http_proxy_module.html |
|