2013年5月3日 星期五

[idea] 反思快取機制


觀察著 Administor 忙碌地處理系統問題,時時監測 Server Loading、httpd 數量、總體記憶體用量,還有久久無法消退的 PENDING REQUEST。配合 Log 的狀態,使我反思一個問題:我們的快取,真的是我們要的嗎?

實作 WebService API 服務時,有些需要耗費大量資源的運算,在結果不太需要頻率更新的時候,我們通常會導入『快取機制』。當採用快取時,程式的流程會變成:


  1. 檢查快取是否有計算結果可用
  2. 如果有快取的結果,則馬上回傳。若沒有則進行 3.
  3. 進行耗費大量資源的運算
  4. 將運算結果放進快取
  5. 回傳結果


快取系統的概念,就是將一個計算結果放進一個具有計時器的儲存空間,當時間一到就會讓儲存的內容過期。在步驟 2. 取不到結果時,就是『計算結果』已經過期所致。因為沒有可用快取,而需走到步驟 3. 進行實際的資料存取。這概念說起來簡單,但別忘了,我們的程式類型是 WebService API。這表示同時間內,可能具有許多的 HTTP REQUEST 進來。若同時間有 N 個 REQUEST 走到步驟 3. 那就會同時有 N 個『耗費大量資源的運算』。

一般來說會使用 Guard Object(或 Barrier) 實作成 Future Pattern 來改善同時間 N 個『耗費大量資源的運算』的問題,在實作正確的情況下,即使 N 個 HTTP REQUEST 進來,也只會有其中一個進行真實的運算。不過因為 Guard Object 的效果,在 Server Administrator 看起來會像是有 N 個 HTTP REQUEST 處於 PENDING 的狀態。

每一個 PENDING 的 HTTP REQUEST 都會佔用系統資源。當 Server 需要持有更多的 HTTP REQUEST 時,那麼就有可能拖慢他的效能。至少 Guard Object 擋住的是真實的 Thread,這個 Thread 綁定的相關資源就佔在那了,至少在 Java Web 來說,Session 跟它的內容物就佔了一些空間。若沒有將 Guard Object 設計好,那可能這 PENDING 會持續到永遠,並且一直累積新的 PENDING REUQEST。

沒設計好不代表有 Bug 實際存在那裡,而是有隱含的『強假設』沒有被處理。像是對 DB 做 SQL Query,『一定』會有資料回來。若 DB 的 Connection Pool 耗盡的行為是『無限等待』,那麼 Guard Object 就會連帶著『甲你攬牢牢』緊抓不放,這就是典型的『強假設』。Guard Object 應該有個停損點來釋放抓住的 HTTP REQUEST,但是實在無法精確預設這個耗時的運算要多久,怎麼設定 timed out 都會成為魔術數字。最後,它可能是一個巨大的 timed out。

這樣的設計,可能對於避免過於耗費 CPU,或短其大量取用記憶體能有較好的效果,但對於耗時的運算可能不是個好方法。在這種架構下,要處理耗時運算的 work around 方法就是定期地發出 HTTP REQUEST 讓失去的快取被補上,並『祈禱』每次等待的都是『機器人』而不是真的 API 使用者。

一切的根源來自於快取模型的限制:時間到了,資料就會消失。而我們的程式就是依賴這個特性去實作的!當資料不見了就執行運算得到新的結果,將它放入快取之內。辜且稱之為:『被動式快取模型』。

理想的情況是:只有系統啟動的第一次,使用者會等待需要快取的運算。快取的資料過期了,仍可繼續使用。在背景快取服務會利用資料存取的 Callback 主動更新內容。相對於我們原先對快取機制的認知,稱作『主動式快取』。

若我們的快取模型是這樣的,那麼只會有第一回合的使用者在等待時間較久,而我們對於快取的 timed out 設定也更有彈性。這樣只需真實地考慮一份資料的更新週期,不太需要在乎使用者是否會等待過久的問題。一來快取的更新不再由使用者發出的 HTTP REQUEST 觸發,這能減輕不必要的 PENDING REQUEST。同時,讓總體的連線等待時間下降,理論上來說,系統整體的負載也會降低。

(此文撰寫於 2011/12/29 日,由於 posterous 要結束了,重貼回 blog)

[daily] 減分


看了 Soft_Job 版最近對於各篇求才文章的推文,其實感覺挺差的。一個職務貼出來,從薪資到期望的能力被『鄉民審判』,這只是將 Soft_Job 版的這一項附加功能給拒絕掉罷了。就客觀條件來看,會什麼語言、使用過什麼工具或 Library 與 Framework。甚至要求到一些 Debug 跟 Trace 等診斷用工具的結果可能都讓人感覺失望。常得到的回應是,要求那麼多,那薪水是多少?有沒有年薪百萬?或是薪水那麼少,要求那麼多,然後又接著一陣的口誅筆伐。漸漸地,大家習慣由列出的客觀條件來扣分,只有對薪水超優的加分。同樣的情境換到別的討論,也是採用預設的扣分動作來進行思考。

我們應該不會以討厭的程度來選擇伴侶吧?即使有一個以上的選擇,我們仍會用喜歡的程度來決定伴侶的。外在客觀的條件只有一開始,你決定要不要去接近他才是影響因素。真的產生了互動,才知道你是否能接納他,甚至發現新的優點。相對的,是否有未在客觀條件中,但你無法接受的缺點呢?像是對於金錢觀的異同,或是月光光的卡奴?

將條件列地詳細並不是為了給大家批判的,而是充份說明公司內有機會接觸到的相關技術。每個人進公司並不太可能一下子就會用上所有列出的需求項目。那可能得輪過幾種不同的專案或者開發項目後才可能遇上,並且也非百分之百的出力。而這些需求的內容,能幫助閱讀者瞭解什麼呢?看到後,讀閱者可以思考,是否有打死都不想碰的領域?如果是這樣的,那你就得將這間公司的優先序往後挪。請注意,只是往後挪而已。如果那個公司仍是你有興趣的不妨進一步談談,說不定,你不想接觸的項目,已經有人包辦了。

像我前一次找工作時,有幾個條件是得在面試時才問得出來的。就拿對我來說,我心中有設定二點要求:

一、要有版本控制系統的工作環境。
二、希望有使用 Issue Tracker。

但後來找到的工作呢?版本控制系統雖然有,但是沒有 changeset 概念的 CVS。有 Bug Tracker,但上面的東西是以 Product 為主的,跟我先前以 RD 任務為單位的使用情況不同,而我開發的多為軟體元件,似乎跟它沒有相關。

即使與心中的條件都不同,但我仍在那工作著!當然是因為談過也相處過後覺得有其他的誘因可以讓我放棄原來設定的條件。我們著手推版本控制系統的世代交替。另外,我專門負責一些軟體元件的製作,大部分的時程可以與產品本身平行。讓我有較充裕的時間維持產出品值的穩定。還有一部分的 Server Side Tool 是由我開發的,只要能達到需求,內部要如何設計其實有很大的自由度的,能不時滿足一下想要玩架構的心情。

好的工作環境得花時間談來的,單看條件就決定,那不就跟古早的作媒是一樣的事嗎?

單純由薪資過濾確實是相當便利而迅速。但你可能會後悔一開始沒有多花時間,而且還暗爽一下省了不少時間。最後,卻因為一開始的偷懶而最後繞了一大圈才知道付出的代價原來這麼大。

(此文撰寫於 2011/11/5 日,由於 posterous 要結束了,重貼回 blog)