在這一系列的第一回我們談到,我們是軟體工程師,不談虛幻的概念,只講能夠量化追蹤的數值指標,那麼, 我們要怎麼把品質轉換程數值指標呢?

軟體品質如何測量

幾個故事

在開始講怎麼做前,我想先講兩個我親身的經驗,在我第一份工作時,前雇主是做手機遊戲的,整間公 司有兩百個員工,但是只有三個是做Server端的,在 2005 年時,多數遊戲都是單機板的,那時公司 簽下 World Series Of Poker 要做多人的線上遊戲,需要開發一個簡易的配對及遊戲訊息交換的伺 服器,當然,大家當年都沒有經驗,所以說,要怎麼樣確保在上線時,不會被用戶衝垮就變成我的工作。

而在我第二份工作時,也有相似的經驗,我們本來已有一個運作中的音樂平台,讓公司內外超過40個Partner使用; 當時,公司又簽下一個合約,說是在三個月後的 6/1 ,會新增 200萬用戶!如何不讓大水衝垮我們的 應用程式,又變成我那幾個月的工作重點。

/images/2012-05-23/troops.jpg

Load Test

寫到這邊,大部份的讀者應該都知道接下來要講的是 Load Test 了,Load Test是個很大的議題,通 常我們在講 Load Test 時,常講的其實是三件不同的事

  • Performance Test
  • Stress Test
  • Longevity Test

這三個測試,用的工具雖然一樣,但是要找個指標跟目的卻是大不相同。

Performance Test

Performance Test 的目地是在找出應用程式的 baseline performance ,做為未來績效評估及設計變 革時的依據。

被 Performance Test 的標的物,通常是已經 feature complete 的模組,然後我們將對模組的每 一個功能,一個一個進行黑箱及白箱測試;然後再用腳本的型態,模擬實際上線的流量,再來測試看看 各功能間對效能的互相影響程度;最後,是找到測試標的物的 Turning Point 及 Scale Factor。

尋找 Best Case Performance

尋找應用程式的 best case performance 大概是最常被忽略的事了, best case performance 指的是你 一個功能的最佳效率,不管怎樣測試,對單一功能來說,怎麼樣你的效率都不可能會再比這個數字 好了;這個數字的第一個用處就在這,如果你的最佳效率比目標效率還糟,剩下來的就不用測了, 因為怎樣都會比這個數字還糟,只能先停下來,回去修改程式碼增進效能。

Best Case Performance 的測法是:

  1. 將應用程式啟動
  2. 先用幾個 request 替應用程式暖身(warm up),以 Java VM 來說,這樣可以讓 Hotspot VM 幫 bytecode 最 佳化,有些需要被啟動的內部原件也會被啟動。
  3. 接著是一個一個的慢慢送一百個 requests ,然後取平均值及標準差。

若是標準差的值過高,或者是反應時間有增長的現像,那麼這個狀況應該記錄下來,然後使用白箱 測試的工具(如 yourkit profiler 去找問題的根源。

除了平均數及標準差外,常用的數字還有

  • mean
  • standard deviation
  • minimum
  • maximum
  • 96 percentile
  • 99 percentile
  • 99.9 percentile
  • 5 minutes moving average
  • throughput
  • error rate

另外,圖表也是常用的工具,因為相較於數字,圖表更容易看出來趨勢的走向;以下圖為例,藍線的 平均反應時間是1.354秒,但跑load test二十分鐘後,每一個 request 都已經超過了平均數,因 此將數字用圖像來呈現是有助於判別數字的。

/images/2012-05-23/chart-1.png

建立 Performance Baseline

接下來的工作,是定出比較的基礎,建立一個你覺得合理的流量,然後就這個比較基礎去找出來不同 狀況下的平均反應時間及處理量的變化。

基礎效能的建立,我們要先控制兩個變數 requests per minutesnumber of concurrent requests ; 透過調整這兩個變數,先找出反應時間較 best case 的流量,然後就此數字開始調整到一個你覺 得合理的值,開始進行 Load Test。

劉接下來我們開始把 requests per minutes(RPM) 倍增number of concurrent requests(CR) 不變 來看,當流量 增加時應用程式的反應時間會如何增長,接著是 RPM 及 CR 同時都倍增,看反應時間如何增長, 依此規則,就二的次方(2^N)開始往上增加,直到 response 開始嚴重衰退,或者 throughput 開 始衰退。

接著,如果你的應用程式支援 Scale-Out ,那麼,我們依此規則,就 RPM, CR, Machines 三 個變數再次就二的次方(2^N)開始調整流量來做測試。

前面這個過程,可以幫我們了解以下幾件事

  • 應用程式對壓力的反應是如何,當流量被增時,反應時間成長的幅度是線性還是成等比級數成長。
  • 處理量 throughput 是否會隨著 request 數增加而增加,是否在超過某個轉折點時,會開始 反轉下降
  • 上述的轉折點,便可當做未來評估是否需要增加機器或者是昇級機器的基準值。當實既須求接近這 個點,或有事件會造成流量超過這個點,那麼,我們就可以在事前進行反應。或者,在監控應用程 式中加入警告,當線上程式逼近這個值的時候,主動告知我們該加機器了
  • 當我們增加機器時,如果應用程式不是寫成完全 stateless 的,而是有共享資料資源時,那麼 ,scale factor便會小於 2,那麼,我們需要關查 scale factor 到底是隨著機器的增加而 不變、還是緩慢成長、或者是快速成長。即使因為某些因素讓我們不能夠準備有實際上線時的機器 數,但是透過分析 scale factor ,我們可以預估上線該使用多少機器。

Stress Test

與 Performance Test 不同的是, Stress Test 是看,應用程式在極度的狀況下,是怎麼樣反 應的,是全面性的停止服務,還是仍能正常處理部份的 request ,其餘未能處理的部份是被堆到排 程中等待處理、還是直接收到錯誤訊息告知服務暫時不可用。而當這極端的狀況停下來後,應用程式 是否會自行回復正常,還是需要 重新啟動才能回復正常。

Stress Test 的方式是直接把 performance test 中 處理量 開始反轉的那個點的流量再 次倍增,看處理量及反應時間會如何的變化。

Longevity Test

Longevity Test 跟前述兩者不同的是, Longevity Test 是在看,應用程式對長時間、持續性、 平緩的流量是如何反應的,是否在某個時間點會有不良的反應,或者是說會有處理量越來越少或反應時 間越來越長的跡象。

透過 Longevity Test 我們可以發覺 - 應用服務是否有 memory leak - 是否有背景的排程工作,造成某個時間點系統資源會被大量耗用

Monitoring

除了從應用程式的外部去觀查應用程式的執行效能,我們還可以更進一步的

  • 從作業系統了解CPU, Memory, Disc I/O, and Network Usage
  • 從JVM 了解 Memory Usage, Object counts, GC Cycles.
  • 從應用程式自訂的 metrics 來觀察 request count, method call time, size of queue, cache hit/miss ratio, etc...

透過截取、記錄、追縱這些數據,搭配上 Performance Test 產生的圖表,我們可以再進一步的了解 應用程式耗用了多少的資源,應用程式的 bottleneck 在那,是 cpu bound, memory bound, disc io bound or network bound.

Note

不要小看了這些監控的細節,我的某個程式,有少量用到 ActiveMQ, ZooKeeper 做溝通,照理說 應該是 cpu or memory bound的應用,但是經過幾次 load test ,發覺不管加多少機器,總處 理量還是不變。後來翻了翻OS來的數據才發現,整個環境的網路頻寬被限制在 250M bps ,再進一 步了解到原來 Amazon EC2 的 Load Balancer 把流量限制在這個數字。

監控的工具有很多種,不過脫不了兩大類 - 監控系統用量 如: Munin, Graphite, RRDTools - 監控系統異常 如: Nagios

這些監控工具,我們不只是可以套用在 Load Test 時使用,更該被大量的佈建在監控線上的應用程 式及外部的服務上,透過長期的追縱,我們可以了解到應用程式及外部的服務的可用度及可靠度。

(全文完)