如何調整壓力測試工具

如何調整壓力測試工具

  如何調整壓力測試工具

  您是否曾經不得不對應用程序進行壓力測試,而最後卻發現不明白結果表明什麼意義?也許問題不是出在應用程序上。也許問題出在配置壓力測試工具的方式上。如果您曾經經歷過這種情況,或者正要進行壓力測試,您就需要考慮以下幾個方面。

  如何進行測試?

  我經常遇到一些開發團隊,他們收到諸如“客戶端將每小時處理20個客戶”此類的性能需求。團隊就試圖把該需求轉化爲某種測試。執行這種測試的常見方法就是以死循環的形式對服務器進行反覆請求,然後靜觀其效。通常事情進行得不是很順利,這就是爲什麼隨後我會作爲一個性能專業化方面的顧問“遇見他們”的原因。通常我問的第一個問題是:“您是如何進行測試的?”一般來說,答案會是:“我們將請求置於循環中,然後計算服務器可以處理的請求的數目。”正是這種回答使我明白首先要做的就是調整測試工具本身。

  如果您不明白上述測試有什麼問題,不要擔心——有很多人和您一樣。進行一次切實可行的壓力測試並不像乍看之下那麼簡單。遇到的問題可能非常微妙,而且通常只有採用不那麼簡單的方法來理清情況才能看清問題。但是這並不是讓您目光呆滯地深入研究馬爾可夫鏈(Markov 
chains)、狀態改變模型、排隊理論、概率分佈等等,讓我們以一種不那麼乏味的、更通俗易懂的方式來說明如何解決這個在許多壓力測試中出現的常見問題。

  測試方式將影響測試

  我們首先要明白的是,雖然測試通常都是從客戶端活動的角度定義的,但是它們必須從以服務器爲中心的視角來看待。以服務器爲視角將只看到客戶端訪問的頻率和處理每個請求所花費的時間。讓我們考慮一個典型例子,即銀行的出納員。出納員通常不知道您是什麼時候到的,也不知道您是從哪裏來的。他們所知道的只是您在這裏,而且您要讓他們爲您做一些事情。現在,隊列中有多少人將取決於人們到達的速度,以及滿足他們的要求所花的時間。

  比隊列中有多少人更重要的是,隨着後來的人不斷補進隊列,房間中的人數是在減少、保持不變還是在增加?與之相隨的另一個問題是,人們進入隊列的速度與離開的速度相比,是快一些、相同還是慢一些?如果離開的速度要比到達的速度快,那麼處理請求的速度要比遞交請求的速度快。第二種情況說明剛剛處理完一個客戶,下一個就到達了。最後一種情況則說明人們到達的速度要比處理的速度快。用數學術語來說,第一種系統是收斂的,第二種處於穩定狀態,第三種則是發散的。這三種情況中房間中的人數都是由利托氏定理(Little's 
Law)決定的。

  只做力所能及的

  對於外行來說,利托氏定理說明了您只能做這麼多工作。其數學版本是這麼說的:系統中的請求數等於請求到達的速度乘以它們在系統中的時間所產生的積。如果它們在系統中的時間取決於流出系統的速度(通常稱爲服務時間),那麼就可以通過觀察請求到達的頻率(請求到達間隔時間)並與服務時間比較,而確定系統處於哪種狀態。

  對於每種情況,利托氏定理都描述了系統是如何處理工作負載的。雖然狀態可能會發生瞬時的迸發和間歇,總體的趨勢還將由平均的狀況決定。例如,在收斂系統中,可能會由於許多人同時進入隊列而產生瞬時的暴漲,但是隊列仍將會騰空,因爲收斂系統的傾向就是趨向空閒。但是,第三種場景是發散的,其中的請求數將會無限增長。它會嗎?這個問題的答案與如何定義發出請求的全域有關。

  在某個隨機的時間點,全域中的用戶將發出一個請求。這肯定是從以服務器爲中心的視角來看全域了。大多數系統都基於一個假設,即在任一個給定的時間點,全域中只有一部分會發出請求。經驗告訴我們,在許多因特網應用程序中,全域中有10%在任意時間點都是活動的。我們需要知道這種信息,如果我們要定義實際的壓力測試的話。例如,如果全域中有1000個用戶,我們會預料有100個每時每刻都在使用系統。由於我們估計會有10%的併發使用,用戶庫又有1000個用戶,所有我們的測試應該模擬100個用戶重複執行一些請求系列。用這種方法定義測試的危害是它反映的是客戶端的視角。

  當我們從以服務器爲中心的視角轉向以客戶端爲中心的視角後,就看不到向服務器發送請求的速度了。如果我們限制或固定爲執行用戶請求所分配的用戶(線程)數目,那麼就看得更模糊了。在這種情況下進行測試,我們將看到服務器正在處理穩定的請求流,而處理請求的時間似乎越來越長。

  每個人都可以參與

  如果我們讓模擬線程儘可能快地發出請求,就是在模擬整個全域(甚至更多)的用戶都在同一時間發出請求。我們假定服務器模型爲單一的,因爲這樣便於理解;多服務器模型的工作方式是相同的,只是更快一些。系統將把請求排隊,並且每次只處理一個。一旦有一個請求清除,線程會立即返回隊列頭部發出下一個請求。雖然這種事件順序似乎說明我們處理的是一個穩定狀態的系統,但我們實際上是在處理髮散系統。它之所以看起來像穩定狀態系統的惟一原因是,我們限制了發出請求的線程數目。正如前面所提到的,在發散系統中,每個後繼用戶的響應時間都要比前一個所經歷的時間長。這意味着平均響應時間將不斷地增長而沒有限制。儘管如此,但是我們人爲地限制了客戶端的數目,因此平均響應時間將穩定在一個點上,該點取決於客戶端數目與處理單個請求所花費時間的乘積。這裏所說的這種系統中的響應時間包括花在隊列中的時間,而且因爲花在隊列中的時間比預料的要少,所以我們又人爲擴大了測量值。最終結果是您的測試限制了您確定系統的可伸縮性的能力。

  如何修復

  要修復壓力測試,需要知道用戶/線程發出請求的速度。所有用戶的速度之和就轉化爲服務器接受請求的速度。一旦確定了這個值,就可以對工具發出請求的速度進行調整。下面的表列出了幾個可以用來維持50個請求每秒(RPS)的值。從服務器的視角來看,工具需要每20ms提供一個請求。這種觀點反映的是單個線程的情況。如果工具配置了兩個線程,那麼對於每個線程,都應該維持40ms的請求間時間間隔。表中還列出了使用5個線程和10個線程的情況下的時間間隔。

  抉擇

  從理論上來說,這個表展示瞭如何使用1個、2個、5個、10個線程來實現所要求的維持50個RPS的目標。但是如果服務時間比請求間時間間隔長的話會怎麼樣呢?這種情況下駐留在服務器中的線程不能使下一個請求排入隊列,工具也不能交付50RPS的預期負載。爲了避免這種情況發生,需要在系統中構建一些空餘時間(slack)。使用大量線程的方案對我們來說通常是不可行的,因爲我們很有可能要受到可用的硬件數目和/或許可證數目(對於商業的負載測試工具來說)的限制。解決方法其實很常見,就是我們需要達到一種維持合適的請求間時間間隔與使用過多的(計算/許可)資源之間的平衡。我們要始終記住,如果測試工具使用的資源(不管是硬件、軟件或是線程)很少,就會影響我們測試的有效性。

  三思而後行

  我們使用Apache 
JMeter來對隨機的Web應用程序進行負載測試,以說明壓力測試工具是如何影響測試結果的。除了要知道應用程序的入口點是Servlet,應用程序的功能以及如何實現的詳細信息對於我們的討論來說並不重要。

  圖1顯示了在平均響應時間下增加線程數目的效果。其中粉紅色的線是沒有調整線程的情況。藍色的線是在每兩個線程之間添加了500ms的空餘時間後的線程。從圖中可以看出,兩種情況的結果差別非常小。每種情況都清楚表明,隨着系統的負載增加,響應時間也會增加。既然我們已經知道服務器的性能會隨總體負載的增加而降低,這樣的結果也就不奇怪了。我們只是在看圖2所示的結果時才能看出存在的問題。

  圖1

  圖2

顯示維持穩定的請求速度的能力最初是受制於線程數目的。同樣這也不能說明問題,因爲有理由假定,在超出特定的線程數目閾值之前,不能維持合理的服務器負載。圖2也顯示,一旦超出了服務器處理請求的能力,線程的增加對工具向服務器發出請求的整體速度的影響就不明顯了。另外一點是,這些“額外”的線程所造成的響應時間的增加確實暗示它們影響了系統的負載。

  問題在於:爲什麼不增加服務器負載的線程看起來會降低服務器的性能?一個可能的答案就是,並不是線程降低了服務器的性能,而是服務器一結束對線程的服務,線程就被排隊了。因爲測量響應時間的計時器必須在將請求發送給服務器時啓動,在收到響應時停止,所以響應時間必然包括線程在隊列中等待服務的所有時間,再加上服務時間。因爲線程一離開就進入系統,就造成了這樣的情況:線程必須等待其他每個線程完成後才能被服務。在這種場景下,線程越多就會造成隊列和響應時間越長。

  利托氏定理告訴我們,這種系統是發散的,而由此可以得出結論:工具妨礙了確定真正的瓶頸(如果存在的話)的能力。

  放慢速度,做得更多

  利托氏定理包括兩個部分:服務時間和頻率。如果我們以工具的眼光來看世界,那麼我們會發現我們不能控制服務時間。但是我們確實能控制頻率。既然前面的工作說明我們進行得太快了(或者說在錯誤的方向上進行得太快了),而我們惟一能控制的就是頻率,那麼我們惟一能做的就是放慢速度。我們可以通過在每兩個請求之間插入間歇來達到這個目的。這將會降低單個線程啓動請求的速度。間歇會降低線程在隊列中的時間,從而提供更符合現實的響應時間。

  爲了測試,我們將啓動50個經過調整的每秒產生9個請求的線程。如果我們發現不能維持合理的請求速度,這些值還可以調整。使用響應時間來評價效果。最後要設置的是間歇時間。可以使用由先前運行得出的數據來幫助我們做出決定。

  回到圖1,我們可以看到,8到9個RPS會產生2到3秒的響應時間。利托氏定理告訴我們,我們需要足夠的線程,以便在2到3秒的時間幀後就可以自由進入系統(假定可以提高平均響應時間)。因此平均的間歇時間大約是3秒。爲了練習,我們將運行一系列的測試來探討值的範圍。

  第一次測試使用2到2.5秒之間的一個隨機選取的值。這個範圍的值的平均間歇時間是3.5秒。可以利用這條信息計算請求的理論速度:用50(線程數目)除以3.5+2(目標響應時間的估測值)。得到的值是9.1RPS。第二次測試使用3到6秒之間的一個隨機值。最終測試使用4到6之間的值。這些測試的結果如圖3所示。

  圖3

  圖3說明增加間歇的時間會使平均響應時間縮短。但是這條信息需要與圖4所傳達的信息相結合。在圖4中,我們可以看到,當間歇時間增加到4-7秒時不能保持要求的向服務器發出請求的速度。我們可以通過添加更多的線程來增加負載,但是這一步中存在最小值,因爲這些測試的確爲我們提供了有效的配置。

  圖4

  這一系列的測試有助於將壓力測試推進到一個更好的配置。我們的結論是:應該配置我們的測試工具,使其使用50個線程,每個線程的間歇時間爲3到6秒。

  結束語

  在開始性能調優實踐(或者爲性能確定基準)之前,需要確認工具不會影響測試。配置良好的工具不會讓我們測量不該測量的數據。不能交付適當的負載或會使我們測量偶然的響應時間的測試工具將會影響對應用程序進行性能調優的工作。要想知道是否發生了這種情況,關鍵是要度量工具以正常速度運行的效果。這種效果可以由工具滿足或支持所要求的每秒的事務或請求數目的能力來確定。工具不應該立刻輪換線程(來發出下一個請求)。如果發生了這種情況,就需要降低工具的速度,以免人爲地使服務器的容量溢出。通常需要試驗幾次以達到測試工具的適當的平衡配置。在測試的早期階段,不要把重點放在響應時間(它會隨着對應用程序調優的過程而改善)上,而是要放在配置好工具上。最後,不要害怕放慢速度,因爲這樣做可能有助於弄清楚到底是什麼影響了應用程序的性能。

發佈了93 篇原創文章 · 獲贊 11 · 訪問量 92萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章