我的上一篇文章描述了如何使用JMeter完成異步REST / HTTP服務的壓力測試或負載測試。 但是,運行這樣的測試通常表明被測系統不能很好地應對不斷增加的負載。 現在的問題是如何找到瓶頸?
深入研究代碼以檢測可疑部分可能是另一種選擇。 但是考慮到潛在的巨大代碼庫,因此考慮到瓶頸隱藏1的眾多可能性,這似乎不太有希望。 幸運的是,有一些工具可以在遙測2的基礎上提供有效的分析功能。 記錄和檢查此類測量值通常被稱為概要分析,而本博文簡要介紹了如何使用Yourkit 3進行此操作。
首先,我們推出我們的SUT( 變體系ü的nDer 牛逼 EST),并使用JMeter的建立系統的負荷。 為此,JMeter可能執行一個測試方案,該方案模擬了多個用戶向SUT發送大量請求的情況。 在測試場景中定義的測試計劃 。 后者可能包含偵聽器 ,這些偵聽器允許捕獲請求的執行時間并提供統計信息,例如最大/最小/可用性請求持續時間,偏差,吞吐量等。 這就是我們檢測到我們的系統擴展性不佳的方式…
在發現之后,我們使Yourkit可以檢索遙測。 因此,SUT的VM由特殊的探查器代理啟動。 探查器工具提供了多個視圖,這些視圖允許實時檢查CPU利用率,內存消耗等。 但是,為了全面分析例如SUT在負載下的性能,Yourkit需要通過所謂的快照捕獲代理提供的CPU信息。
建議在單獨的計算機上運行SUT,JMeter和Yourkit,以避免篡改測試結果。 在同一臺機器上運行例如SUT和JMeter可能會降低吞吐量,因為JMeter線程可能會消耗大量可用的計算時間。
考慮到此設置,我們將介紹一個概要分析會話的小示例。 以下代碼段摘錄了我們用作SUT的基于JAX-RS的服務4 。
@Path( '/resources/{id}' )
public class ExampleResourceProvider {private List<ExampleResource> resources;[...]@Override@GET@Produces( MediaType.TEXT_PLAIN )public String getContent( @PathParam( 'id' ) String id ) {ExampleResource found = NOT_FOUND;for( ExampleResource resource : resources ) {if( resource.getId().equals( id ) ) {found = resource;}}return found.getMessage();}
該服務在ExampleResource
實例列表中執行查找。 ExampleResource
對象只是將標識符映射到以String
表示的消息。 找到給定標識符的消息將返回。 在使用GET
請求調用服務時,您可以使用瀏覽器測試結果:
出于演示目的,服務的粘合代碼以無序方式使用500000個元素初始化列表。
一旦運行了SUT,就可以使用JMeter在負載下對其進行設置。 該測試計劃一次執行大約100個并發請求。 如下圖所示,平均請求執行時間約為1秒。
Yourkit在JMeter測試計劃執行期間記錄的CPU遙測揭示了請求執行時間長的原因。 選擇配置文件快照的“ Hot spots
選項卡顯示列表迭代消耗了大約72%的CPU利用率。 查看列出了所選熱點方法的調用者樹的Back Traces
視圖,我們發現示例服務方法導致列表迭代。
因此,我們在下一步中更改服務實現,以對有序列表使用二進制搜索進行ExampleResource
查找。
@Override@GET@Produces( MediaType.TEXT_PLAIN )public String getContent( @PathParam( 'id' ) String id ) {ExampleResource key = new ExampleResource( id, null );int position = Collections.binarySearch( resources, key );return resources.get( position ).getMessage();}
之后,我們重新運行JMeter測試計劃:
現在平均請求大約需要3毫秒,這是一個很大的改進。
查看相應的CPU性能分析會話的Hot spots
,可以確認由我們的方法引起的瓶頸已經消失。
誠然,以上示例中的問題似乎非常明顯。 但是我們在生產代碼中發現了一個非常相似的代碼,它隱藏在系統的深度中(可恥的是……)。 重要的是要注意,在開始壓力和負載測試之前,問題并沒有變得很明顯5 。
我想我們在找到原因之前(如果有的話)將花費大量時間手動檢查代碼庫。 然而,剖析會議將我們直接指出了所有邪惡的根源。 通常情況下,實際問題并不難解決。 因此,概要分析可以幫助您更有效地處理一些工作。
至少它對我有用-順便說一下-這也很有趣
- 請注意,導致瓶頸的代碼也可能屬于第三個庫。 ?
- 當我現在在一個客戶項目中進行這種分析時,我想到了寫這篇文章的想法?
- 我在這里沒有做任何工具廣告或評級-我只是使用我熟悉的工具來給出一個更抽象的概念的可復制示例。 市場上有很多更好的工具可以滿足您的需求?
- 請注意,本文中的代碼片段的唯一目的是作為如何查找和解決性能瓶頸的示例。 這些代碼片段編寫得很差,不應以任何方式重復使用! ?
- 根據我的經驗,新創建的代碼庫包含其中的一些塊是很常見的。 因此,有這樣的測試是必須的,以便找到性能問題的顧客發現他們在生產之前... ?
參考:來自JCG合作伙伴 Frank Appel的JMeter和Yourkit對REST / HTTP服務的性能分析,位于Code Affine博客上。
翻譯自: https://www.javacodegeeks.com/2012/11/performance-analysis-of-resthttp-services-with-jmeter-and-yourkit.html