Centos

Varnish 有時(最多約 5% 的請求)會觸發 err_too_many_redirects,在 docker 中執行並結合 plesk for wordpress

  • January 13, 2022

我們已經按照這些說明https://support.plesk.com/hc/en-us/articles/115001888894-Does-Plesk-support-Varnish-並且能夠讓它“正常”工作,它為 wordpress 服務網站通過清漆和速度是驚人的。一切都很好,但是我們的正常執行時間機器人時不時地報告短暫的停機時間(非常不規律,但每天 1 到 8 次,持續時間 <5 分鐘,全天不同時間)。

經過各種測試後,我們注意到 wp-admin url 存在問題,我們得出結論,這是因為我們的 DirectoryIndex(預設為 index.html),我們通過添加 ‘DirectoryIndex index.php 解決了這個問題’ 到解決該問題的“附加 Apache 指令”。

對我們來說似乎很有趣的一件事是,當我們更改 PHP(FPM) 的服務方式時,它會影響相同的錯誤。當我們通過 NGINX 提供服務時,我們也會得到 err_too_many_redirects,如果我們通過 Apache 提供服務,它 95% 的時間都可以工作。

我在下面添加了一些(varnishncsa)日誌記錄,當標題響應狀態為 301 時,我們處於循環中:

172.17.0.1 - - [11/Jan/2022:13:54:55 +0000] "HEAD http://[the varnish domain]/ HTTP/1.0" 200 0 "https://[the varnish domain]" "Mozilla/5.0+(compatible; UptimeRobot/2.0; http://www.[uptimerobot].com/)"

172.17.0.1 - - [11/Jan/2022:13:56:51 +0000] "GET http://[the varnish domain]/ HTTP/1.0" 200 11184 "-" "-"

172.17.0.1 - - [11/Jan/2022:13:58:31 +0000] "HEAD http://[the varnish domain]/ HTTP/1.0" 301 0 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36"

172.17.0.1 - - [11/Jan/2022:13:58:32 +0000] "HEAD http://[the varnish domain]/ HTTP/1.0" 301 0 "http://[the varnish domain]" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36"

在此之後,我們記錄了 8 次以下日誌: 172.17.0.1 - - [11/Jan/2022:13:58:32 +0000] "HEAD http://[the varnish domain]/ HTTP/1.0" 301 0 "https://[the varnish domain]/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36"

然後一個: 172.17.0.1 - - [11/Jan/2022:13:58:34 +0000] "GET http://[the varnish domain]/ HTTP/1.0" 301 238 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/96.0.4664.110 Safari/537.36"

然後7次: 172.17.0.1 - - [11/Jan/2022:13:59:55 +0000] "HEAD http://[the varnish domain]/ HTTP/1.0" 301 0 "https://[the varnish domain]" "Mozilla/5.0+(compatible; UptimeRobot/2.0; http://www.[uptimerobot].com/)"

然後 22 次: 172.17.0.1 - - [11/Jan/2022:14:00:17 +0000] "GET http://[the varnish domain]/ HTTP/1.0" 301 238 "https://[the varnish domain]" "Mozilla/5.0+(compatible; UptimeRobot/2.0; http://www.[uptimerobot].com/)"

在那之後,一切似乎又好了。

更新:檢查日誌

@thijs-feryn 指出了一些有趣的事情,這使我們得出結論,我們已經過早地駁回了一個舊理論。因為我們確信 X-Forwarded-Proto 已被傳遞,因為它在我們的“附加 apache 標頭配置”中。

然而,在仔細閱讀他的回復後,我們了解到 X-Forwarded-Proto 並沒有通過每個請求(至少不是在損壞的請求上)。他指出

$$ another varnish domain $$在類似的請求中似乎很好地通過了這個記錄。 在對配置進行了一些仔細的比較之後,只有一件事讓我們印象深刻,那就是 plesk 中的首選域

$$ another varnish domain $$被設置為“無”,並且對於$$ the varnish domain $$被設置為$$ the varnish domain $$. 所以我們去了www。

$$ the varnish domain $$在我們的瀏覽器中,這似乎引發了問題。我們在這裡也將“首選域”切換為“無”,現在是 www。$$ the varnish domain $$重定向到$$ the varnish domain $$正好。 假設

似乎 plesk 自己的重定向忽略了“HTTP 的附加指令”,因此沒有添加“Vary: X-Forwarded-Proto”。我們將對此進行監控,並儘快發布更新,當我們完全確信這是原因時。

該問題可能與記憶體方面缺乏協議意識有關。很典型的是,應該重定向到 HTTPS 請求的 HTTP 請求最終會進入記憶體,這會無條件地將使用者重定向到 HTTPS 版本,即使他們實際請求的是 HTTPS 版本。

根據您使用的網路伺服器的類型,有多種方法可以解決此問題。

清漆日誌輸出

但在我們得出結論之前,我想看看一些varnishlog輸出。

當重定向循環發生時,我希望看到以下命令的輸出:

varnishlog -g request -q "ReqUrl eq '/'"

假設這個問題也出現在我們作為 VSL 查詢添加到varnishlog命令的首頁上。

我注意到你的varnishncsa輸出,但不幸的是它在輸出方面太有限了。varnishlog對於調試來說要好得多,而varnishncsa只是。

檢驗假設

如果重定向循環確實是由於缺乏協議意識導致的,我們可以觸發如下問題:

  • 執行varnishadm ban obj.status "!=" 0清空記憶體
  • 呼叫網站的純 HTTP URL 以確保記憶體此版本
  • 呼叫網站的 HTTPS URL 以檢查您是否卡在重定向循環中

解決問題

如果所有測試加起來並且假設得到證明,那麼解決方案實際上非常簡單。

如果您使用 Apache 作為網路伺服器,您可以將以下內容添加到您的.htaccess文件中:

SetEnvIf X-Forwarded-Proto "https" HTTPS=on
Header append Vary: X-Forwarded-Proto

否則,您還可以將以下程式碼添加到您的 VCL 文件中:

sub vcl_backend_response {
   if(beresp.http.Vary) {
       if(beresp.http.Vary !~ "X-Forwarded-Proto") {
           set beresp.http.Vary = set beresp.http.Vary + ", X-Forwarded-Proto";
       }
   } else {
       set beresp.http.Vary = "X-Forwarded-Proto";
   }
}

添加X-Forwarded-ProtoVary標頭將確保 Varnish 在記憶體中為 HTTP 和 HTTPS 創建單獨的對象。

我還假設您的 TLS 代理實際上發送了一個X-Forwarded-Proto標頭。

更新:檢查日誌

在評論中反复討論之後,我通過https://pastebin.com/QzPh1r5R收到了一些有見地的日誌,這些日誌解釋了發生了什麼。

** &lt;&lt; BeReq &gt;&gt; 951078你可以看到X-Forwarded-Proto: http標題。這意味著請求是通過純 HTTP 請求發送的。這種類型的請求應該會導致 301 重定向,它會根據以下日誌行進行:

--  BerespProtocol HTTP/1.1
--  BerespStatus   301
--  BerespReason   Moved Permanently
--  BerespHeader   Date: Thu, 13 Jan 2022 08:55:17 GMT
--  BerespHeader   Server: Apache
--  BerespHeader   Location: https://[the varnish domain]/
--  BerespHeader   Content-Length: 238
--  BerespHeader   Content-Type: text/html; charset=iso-8859-1
--  TTL            RFC 120 10 0 1642064118 1642064118 1642064117 0 0 cacheable

不僅會發生重定向,還會記憶體 120 秒。看到沒有Vary: X-Forwarded-Proto標題也很有趣。

稍後,* &lt;&lt; Request &gt;&gt; 951080事務會在日誌中彈出。我們看到以下請求標頭:

-   ReqHeader      X-Forwarded-Proto: https
-   ReqHeader      Host: [another varnish domain]

所以這是對另一個 Varnish 域的 HTTPS 請求,由於某種原因,它會導致記憶體命中並返回一個Vary標頭:

-   RespHeader     Vary: Accept-Encoding,Cookie,X-Forwarded-Proto
-   VCL_call       HIT
-   Hit            886585 90003.966201 10.000000 0.000000

您不僅可以看到命中,還可以斷定對像是由 transaction 插入到記憶體中的886585

雖然有一個Vary標題很好,但這個包含的Cookie值是危險的。這意味著對於呈現給 Varnish 的每個可能的 cookie 值,都會在記憶體中儲存一個單獨的對象。這是非常危險的,所以請CookieVary標題中刪除並堅持使用Vary: Accept-Encoding, X-Forwarded-Proto.

我查看的最後一筆交易是* &lt;&lt; Request &gt;&gt; 951082. 它有一個X-Forwarded-Proto: https請求標頭,不應導致 301 重定向,但不幸的是它確實如此。

Hit標籤公開了一些有趣的資訊:

-   Hit            951078 82.391648 10.000000 0.000000

被命中的對象最初是由事務插入記憶體中的951078。如果您密切關注,那是我們介紹的第一個。此事務是導致 301 重定向的僅 HTTP 事務。

這正是返回的對象。因此,即使您請求的是 HTTPS 內容,您仍然會被重定向,這就是您最終陷入無限循環的方式。

如果您查看事務返回的響應,則951082看不到Vary標頭:

-   RespProtocol   HTTP/1.1
-   RespStatus     301
-   RespReason     Moved Permanently
-   RespHeader     Date: Thu, 13 Jan 2022 08:55:17 GMT
-   RespHeader     Server: Apache
-   RespHeader     Location: https://[the varnish domain]/
-   RespHeader     Content-Length: 238
-   RespHeader     Content-Type: text/html; charset=iso-8859-1
-   RespHeader     X-Varnish: 951082 951078
-   RespHeader     Age: 37
-   RespHeader     Via: 1.1 varnish (Varnish/7.0)

**結論:**請確保將X-Forwarded-Proto其添加到您的Vary標題中。它將防止卡在重定向循環中。

引用自:https://serverfault.com/questions/1089685