12/22/2006

Rails Cache 再探:Page Cache 使用心得

以前介紹過 Rails Cache 第一步 : Page Cache。自從摸透了 Page Cache 之後,本人實在愛不釋手,至今已經用 Page Cache 寫過 3 ~ 4 個敝公司的行銷專案。我發現到 Page Cache 最大的特色就是可以產生一個完全靜態的頁面,而且完全不經過 cgi 就直接給 Web Server讀取。所以當你使用 page cache ,這意味著
  1. 最快的速度(靜態頁面絕對最快)
  2. 最高的安全性(不跑 cgi 絕對最安全)
  3. 前端 Web Server 完全不需要安裝 Ruby on Rails
等絕對優勢。

當然你會開始發問啦,這個東西只有幾個靜態頁面,但是遇到需要動態更新的資料的頁面要怎麼辦?我的回答是『不怎麼辦呀!!!』,本來 Page Cache 就不是用在這方面的,他是用在特殊的用途的,而且這些特殊用途其實還蠻常見的。

適用範圍

有時候某些流量超級巨大的頁面,像是一個網站的首頁,通常流量都超大的。這個時候網站的首頁還要動態產生那就實在太苦了機器,還是讓 Page Cache 產生出來靜態頁面,然後一個小時更新一次就好。

或是我們寫到某些計算量太大的頁面,像是一些資料庫資料的分析,不管怎麼算都需要計算個 10分20分鐘的時候,既然無法每個 request 都動態產生頁面,還是用 cache 一天產生一次這樣的大量計算的頁面吧,而且通常這種計算量大的頁面都不會要求即時的。

另外一個使用範圍,就是一些小型行銷專案。有些案子是一些小活動的頁面,通常他們只需要一個到兩個小頁面即可,這個時候也可以使用 Page Cache。不過這個時候我用 Page Cache 的原因在於通常負責行銷活動的機器有時候也會派上其他用途,一家公司通常不會特別撥一個機器去做活動頁面,這樣太浪費機器的資源。為了擔心行銷活動跟其他任務的機器綁在一起,如果我的 cgi 哪裡出了問題,影響到公司其他 team 的任務就不好意思了。另外一個原因是其他 team 的機器如果跑的是其他的任務,通常 frontend web server 是經過某些用途特製化過了,網管不會希望這樣特製化的 frontend web server灌太多其他 cgi 程式影響原本的用途。這時候我也會使用 Page Cache 來寫 Ruby on Rails,這個方面是取其安全性跟
frontend web server 不需要安裝 cgi的特色。

使用技巧

至於要怎麼使用呢?我把我目前寫行銷專案的技巧講出來好了。

首先你需要安裝一個 Mongrel ,然後跑在你的 Ruby on Rails程式在 80 以外的 port,這裡用 4000 來說明好了。再來用 Firewall 去擋住 4000 port,只允許 localhost 可以 access 4000 port,這樣就相當安全了。

再來請在每一個 cache page 的 action 以外,另外寫一個 action 專門 expire 這個 page cache。這裡假設 action 名字叫做 expire。

最後用 crontab 在本機端上定期 trigger一下剛剛寫好的那個 expire action,記得要去 trigger Mongrel 開的 port 4000,而非 80 port。這裡就可以做到定期rotate refresh cache 的功能,並且剛剛不是有說到 firewall 僅僅允許 localhost 去 access ,就是為了讓本機端去做到定期 rotate 的功能。

結論

到目前為止,雖然這個方式算是 special case 專用,但是這個方式,我覺得相當的好用而且簡單易懂,兼顧 Ruby on Rails 的方便性,並且擁有優異的速度跟安全性,程式碼僅僅多加個四五行 add / expire cache 的程式碼。如果有人想將 Ruby on Rails 導入公司,但是 CTO 因為延展性,速度,安全性等等理由去打發你的話,可以先考慮使用這個方式來導入。通常一不導入則已,只要一導入 Ruby on Rails ,你的同事嘗了 Ruby on Rails 的甜頭,就很難回頭去寫原本的 PHP 或是 Java 了 XD


延伸閱讀


4 則留言:

Gea-Suan Lin 提到...

404 funky cache 的技巧應該比較簡單,而且是已經被許多巨型站台考驗過。

GSR 提到...

如果我的理解沒錯的話
Rails的page cache本身就像是404 funky cache了

GET index.html
找的到這個檔案的話: apache直接response
找不到檔案的話: apache->cgi->rails->產生頁面並response

要做的事也只是crontab定期去把cache殺掉而已

Gea-Suan Lin 提到...

404 funky cache 與這篇提到 cache 的想法一樣,但量大的時候會發現 cache 機制不穩定,要用靜態檔案才行。

用檔案的另外一個好處是真正能把 OS 的極限飆出來,在 unix 環境下面幾乎都有支援 sendfile(),這個函數從檔案讀出來送到網路卡是不用經過 userland space,使用的資源會比自己透過 cache 少,這樣可以讓 PHP 之類的跑的比較順。

另外一個方便的地方是頁面更新的時候直接砍檔案 (砍所有前端機器的檔案),下次有人來讀的時候就會再生新的出來。

thegiive 提到...

挖,大神來了!

不過 page cache 在讀取時,並沒有透過 Ruby on Rails 的 cache 機制。而是他會直接 access 一個靜態檔案。

舉個例子,今天 http://abc.com/hello/hi 這個 action 如果做 page cache,他會自動在裡面public 資料夾底下的 hello 目錄下面產生一個 hi.html。所以下次 query 這個 http://abc.com/hello/hi 這個 action, web server 會直接讀取 hi.html,而完全不會經過任何 cgi。從頭到尾都只是讀取 request -> 讀取靜態檔案而已。

這應該是 GSR 所說的 page cache 跟 funky cache 一致的意思。