使用 Varnish 優化移動端站點

w3cplus發表於2015-04-05

想象一下,你剛剛釋出了一篇博文,並分享到了社交網路。然後,這篇文章恰巧被大V看中再次分享了出去,立即吸引了數百粉絲的目光,引導他們湧入了你的網站。看到這麼多的訪客量,以及它們的評論,你內心激動不已。突然之間,你的網站就掛掉了,滿屏的資料連線錯誤……

或者假想另一種情境,你一直很努力地創業。突然有一天,一個大V在社交網路表達了對貴公司的喜愛之情,字裡行間滿滿的讚歎。關注這個大V的粉絲心動了,又湧入了你的網站。不幸的是,點選連線後卻無法進入你的網站,或者進入後無法註冊使用者,甚至頁面相應超時,無法獲取產品的序列號。儘管你在社交網路上對此非常誠懇的表達了歉意,但眾多的瀏覽者都不會再有興趣。

這些假想其實非常普遍。在我的工作中,就經常發現,當網站資訊在社交網站流傳開來的時候,移動裝置的訪問請求就會驟增。這也表明,在社交網路中,越來越多的人開始使用移動裝置,而不是傳統的桌面應用。此外,大多數的移動使用者都在使用公共 Wi-Fi 以及其他低速網路來訪問網站。所以,快速載入網站的任何優化措施,都會有利於使用者的訪問。

在本文中,我會向你介紹 Varnish 網頁應用加速器(Varnish Web application accelerator)——這是一個免費、簡單的工具,大大改善大規模突發性訪問狀態下的響應能力。

使用 Varnish 優化移動端站點

亮點

對於大多數的網站來說,眾多使用者請求訪問的核心內容大都是一致的——尤其是每天都會更新內容的入口網站。不用多說你也會理解,圖片、CSS 和 JavaScript,這些靜態資源往往有較長的有效期(譯者注:有利於在不同頁面間複用)。但你可能沒有深入思考過,通常在部落格平臺或者是內容管理系統中,響應使用者的請求後,所返回的資料內容,大多也是相同的。

來自社交網路的使用者進入一個部落格後,並不會請求完全一致的資訊。除了圖片、JavaScript 和 CSS,這些資訊還包括 PHP 動態生成的內容,以及從資料庫查詢到的資料。訪問部落格中的某一篇博文,所需要傳送的每一條請求,不僅僅是在獲取網路伺服器提供的靜態資源,還需要配合 PHP 指令碼,使用資料庫連線以及資料庫表單檢索等功能。

資料庫連線的數量越多,Apache 需要處理的程式就會越多,而總的處理能力是由限度的。相應的,訪客的數量越多,服務就會越不穩定,掙到的錢就會越少。

這就是類似 Varnish 的 HTTP 快取發揮作用的地方。如此一來,從瀏覽器發出的請求,不再直接到達建立和維護網頁的伺服器,而是到達 HTTP 快取伺服器。如果快取伺服器中存在所需頁面,那麼直接從伺服器的記憶體返回相應的資源,不再動用 Apache 伺服器和資料庫。如果所需頁面不再快取中,那麼就像傳統方式一樣,使用 Apache 伺服器來處理。Apche 處理完成之後,就會將這個頁面儲存到 HTTP 快取伺服器中,等到下一次請求相同頁面時就可以直接返回了。

將頁面儲存在記憶體中,其響應速度遠快於將其儲存在硬碟中。此外,當請求的頁面為於 HTTP 快取伺服器中時,就無需動用 PHP 或者資料庫來處理相關操作。這也讓 PHP 和 伺服器能夠有更多的效能來處理更繁重的程式和連線。比如,上面提到的被大 V 稱讚的那家初創公司面臨的情境,眾多粉絲點選的連結其實只是網站中的少數幾個頁面——而這些完全可以儲存在快取記憶體伺服器中,當需要時直接從記憶體響應請求。此時,準備註冊的使用者就會感到整個流程非常順利,因為後臺指令碼和資料庫連線的處理能力非常寬裕,完全不受突發性請求的影響。

原理

下面這個示意圖,展示了 Apache 伺服器響應請求後生成站點內容的基本流程。在這個例子中,為了請求相同的頁面,一共從瀏覽器傳送了五條指令給 Apache,而 Apache 很呆板的對每條請求都做了詳細的處理。

使用 Varnish 優化移動端站點

是的,Apache 處理了每一條請求——影像,CSS,JavaScript 和 HTML 檔案。如果 PHP 中有某個檔案,就會解析一次。如果需要請求資料庫的資訊,那麼就要執行一次資料連線,進行 SQL 查詢等操作。最終,在 Apache 返回給瀏覽器資訊之前,資料庫返回相關資訊組裝成完成的頁面。

如果我們在 Apache 之間使用 Varnish,我們就可以形成這樣的一個流程:

使用 Varnish 優化移動端站點

如果瀏覽器請求的資源和頁面已經存在快取中,那麼 Varnish 就會直接從記憶體返回這些資源,而 Apache、PHP 和 MySql 完全不需要進行重複的操作。如果瀏覽器請求的資料不再快取中,那麼 Varnish 就會將相關的處理工作轉移給 Apache,讓 Apache 處理相關的細節。這種方式的優勢就在於,只讓 Apache 處理必要的工作,一旦生成了所需的資源,該資源就會被儲存到快取伺服器的記憶體中。當再次有請求訪問這些資源時,Varnish 就完全有能力應付了。

這個工具還有另一項好處。在 Varnish 的屬於中,你所配置的 Apache 伺服器,被稱為“處理後臺”。Varnish 允許配置多個處理後臺。所以,你可以同時執行兩個網路伺服器,比如,一臺使用 Apache 處理 PHP 頁面,一臺使用 nginx 處理靜態資源。在 Varnish 中設定成功後,就可以從正確的伺服器獲取相應的資源。在本篇教程中,我們將著眼於一個簡單的示例。

震驚!快教我吧

安裝和配置 Varnish 相當簡單。你需要獲得伺服器的 root 許可權(sudo),才能安裝 Varnish。因此,你的網站需要託管在類似 VPS 的伺服器上。現在 VPS 的價格也不是那麼昂貴了,而且使用 Varnish 也會影響大家選擇 VPS 而不是共享伺服器。

有些 CMS 擁有的外掛,可以直接使用 Varnish,或者將其整合進控制皮膚——通常可以更輕鬆地清空快取。當然,你可以將 Varnish 融入任何的 CMS 或者靜態網站中,而不需要特殊的配置。

在演示安裝 Varnish 的整個流程之前,我會假設你已經在系統中使用 Apache 作為伺服器了。雖然我在使用 Debian Linux,但安裝過程中用到的軟體包對其他分發版本也是適用的(只是系統中的檔案路徑會有所不同)。

在開始之前,先檢查一下網站是否正常執行在 Apache 上。如果你使用的伺服器是個新品,或者你想在本地虛擬機器上嘗試 Varnish,那麼請確保配置一個虛擬主機,並可以用瀏覽器開啟這個伺服器的測試頁面。

安裝 Varnish

各個平臺的詳細安裝說明請參考 Varnish 官方文件。因為我使用的是 Debian Wheezy,所以我會遵循 Debian 部分的說明。一旦 Varnish 安裝完成,終端中就會輸出下面這段話,提示你安裝成功了:

[ ok ] Starting HTTP accelerator: varnishd.

Apache 預設監聽來自 80 埠的請求。這個埠接收請求,所以為了配合 Varnish 置於 Apache 之前的佈局,需要修改埠,讓 Varnish 監聽 80 埠,同時將 Apache 的埠修改為一個與之不同的值——一般來說是 8080。然後在 Varnish 中配置相關資訊,讓 Varnish 連通 Apache。

重新配置 Apache

為了修改 Apache 當前的監聽埠,需要使用 root 許可權開啟 /etc/apache2/ports.conf 檔案,找到下面這兩行:

NameVirtualHost *:80
Listen 80

修改為:

NameVirtualHost *:8080
Listen 8080

如果看到了下面這兩行,只需要修改 80 為 8080 即可:

NameVirtualHost 127.0.0.1:80
Listen 80

然後儲存該檔案並開啟預設的虛擬主機檔案,該檔案應該在 /etc/apache2/sites-available。在這個檔案中,找到下面這一行:

<VirtualHost *:80>

修改為:

<VirtualHost *:8080>

當然,你也需要修改其他用到的虛擬主機。

配置 Varnish

開啟 /etc/default/varnish 檔案,將頁面滾動到沒有註釋、以 DAEMON_OPTS 開頭的部分。將這一部分編輯如下,使 Varnish 監聽 80 埠:

DAEMON_OPTS="-a :80 
-T localhost:1234 
-f /etc/varnish/default.vcl 
-S /etc/varnish/secret 
-s malloc,256m"

開啟 /etc/varnish/default.vcl 檔案,檢查預設的後臺埠並設定為 8080,用來連通 Apache :

backend default {
  .host = "127.0.0.1";
  .port = "8080";
}

在 root 許可權下,使用如下命令重啟 Apache 和 Varnish:

service apache2 restart
service varnish restart

檢查先前的測試頁面是否仍然可以連線。如果可以,那麼你可能想知道如何測試網站是否已經被快取到了 Varnish 上。事實上有好幾種方式,最簡單的是使用 cURL。請在命令列中輸入以下命令:

curl http://yoursite.com --head

此時獲得響應應該類似於 Via: 1.1 varnish。

你也可以檢視由 Varnish 生成的靜態資源。在終端中,輸入 varnishstat,然後在瀏覽器中重新整理頁面,就會看到點選率逐漸增加。如果是由 Varnish 提供的資源,那麼會標識為 hit;如果由 Apache 或其他後臺提供,標識為 miss。

另一個有用的工具是 varnish-top。首先在命令列中輸入 varnishtop -i txurl,然後在瀏覽器中重新整理頁面。這個工具將會顯示哪些頁面是由 Varnish 提供的。

清除快取

當頁面被快取之後,當你改動 HTML 或者 CSS 檔案,並不會立即看到更新的部分。這經常讓我出差錯。雖然我知道在 Apache 之前有個快取伺服器,但還是經常會犯傻“剛剛我的修改哪去了?”在命令列輸入 varnishadm “ban.url .” 即可清除全部的快取。

你也可以通過 HTTP 控制 Varnish。這方面有很多外掛,比如服務於 WordPress 的 Varnish HTTP Purge,可以直接通過管理介面清除快取。

自定義

也許,你會想通過了解一些 Varnish 的工作原理來微調它的配置。如果按照上述步驟配置 Varnish,一旦靜態資源和頁面被快取到記憶體中,會逐漸積累起大量的靜態資源和頁面。

Varnish 只會快取那些不會影響安全的資源,也因此有時不會快取一些你認為會被快取的資源,比如,cookies。

在預設配置中,如果設定了 cookie,那麼 Varnish 就不會快取相應的內容。所以,如果你的站點為不同使用者提供不同的內容,比如個人資料,那麼你肯定不會為了一個使用者快取所有人的資料。不過,有時你又會希望忽略一些 cookies,比如為了某些分析工作。如果網站並不提供任何個人資料,那麼唯一需要考慮 cookies 的地方就是後臺管理部分——如果 Varnish 快取了後臺管理的部分,那麼檢視修改就會非常不方便。

讓我們修改一下 /etc/varnish/default.vcl 檔案。假設你的後臺管理部分在 /admin,那麼你需要新增如下內容:

sub vcl_recv {
  if ( !( req.url ~ ^/admin/) ) {
    unset req.http.Cookie;
  }
}

有些 cookies 可能非常重要,比如已經登入的使用者 cookies 就不應該快取。所以,你就不會希望排除所有的 cookies。此處使用一個正規表示式可以定義那些 cookies 是我們需要的。也可以下哦那個網上找到很多解決這個問題的方案。對於分析工具的 cookies,你可以新增如下內容:

sub vcl_recv {
  // Remove has_js and Google Analytics __* cookies.
  set req.http.Cookie = regsuball(req.http.Cookie, "(^|;s*)(_[_a-z]+|has_js)=[^;]*", "");
  // Remove a ";" prefix, if present.
  set req.http.Cookie = regsub(req.http.Cookie, "^;s*", "");
}

Varnish 文件中有一個專門的部分講解 cookies

在大多數情境下,按照上述配置 Varnish,並移除分析工具的 cookies,將會大大加快網站的訪問速度。一旦 Varnish 建立並執行起來,在熟悉了配置的基礎上,你就可以微調配置,從快取規則中獲得最佳效能。

進階

更多資料,請參考 Varnish 官方文件。你應該從現在起嘗試一些操作例項,深入瞭解 Varnish 的基礎知識。

相關文章