在這一系列的第一回我們談到,我們是軟體工程師,不談虛幻的概念,只講能夠量化追蹤的數值指標,那麼, 我們要怎麼把品質轉換程數值指標呢? 軟體品質如何測量 =============================================================================== 幾個故事 ------------------------------------------------------------------------------- 在開始講怎麼做前,我想先講兩個我親身的經驗,在我第一份工作時,前雇主是做手機遊戲的,整間公 司有兩百個員工,但是只有三個是做Server端的,在 2005 年時,多數遊戲都是單機板的,那時公司 簽下 World Series Of Poker 要做多人的線上遊戲,需要開發一個簡易的配對及遊戲訊息交換的伺 服器,當然,大家當年都沒有經驗,所以說,要怎麼樣確保在上線時,不會被用戶衝垮就變成我的工作。 而在我第二份工作時,也有相似的經驗,我們本來已有一個運作中的音樂平台,讓公司內外超過40個Partner使用; 當時,公司又簽下一個合約,說是在三個月後的 6/1 ,會新增 200萬用戶!如何不讓大水衝垮我們的 應用程式,又變成我那幾個月的工作重點。 .. image:: /images/2012-05-23/troops.jpg :width: 800 px 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 都已經超過了平均數,因 此將數字用圖像來呈現是有助於判別數字的。 .. image:: /images/2012-05-23/chart-1.png :width: 480 px .. _yourkit profiler: http://www.yourkit.com/ 建立 Performance Baseline ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 接下來的工作,是定出比較的基礎,建立一個你覺得合理的流量,然後就這個比較基礎去找出來不同 狀況下的平均反應時間及處理量的變化。 基礎效能的建立,我們要先控制兩個變數 **requests per minutes** 及 **number 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 時使用,更該被大量的佈建在監控線上的應用程 式及外部的服務上,透過長期的追縱,我們可以了解到應用程式及外部的服務的可用度及可靠度。 (全文完) ===============================================================================