做爲一名開發者,咱們最長聽到的就是編程界的三高:java
高性能、高併發、高可用。git
聽起來很是高大上,可是性能到底如何呢?又該如何評定呢?github
此次咱們談一談性能測試,看一看到底什麼樣才叫作高性能。數據庫
本文主要從如下幾個方面進行討論。編程
(1)性能測試是什麼?後端
(2)爲何須要性能測試?緩存
(3)性能測試如何作?服務器
(4)有哪些性能測試的工具網絡
老馬曾經說過,你想理解一件事物,首先必須先定義它。架構
這裏直接引用一下百科中的定義:
性能測試是經過自動化的測試工具模擬多種正常、峯值以及異常負載條件來對系統的各項性能指標進行測試。
性能測試的定義也不難理解,每每定義自己闡述了性能測試的做用。
若是你是一名開發、測試,平時接手過很多需求,可能性能測試接觸的也很少。
每個需求,都有對應的功能性需求和肺功能性需求。
功能性需求是產品需求文檔中最直接的,須要實現的功能目標。簡稱,能用就行。
非功能性需求則要寬泛的多,架構設計是否合理?是否便於後期拓展?是否便於監控?代碼實現是否優雅?文檔註釋是否完整?
就像你寫了一隻鳥,鳥頭作螺旋槳非能飛起來,可是在架構設計上多是不合理的。
一個查詢功能,用戶點擊查詢,10S 種才返回數據,功能上是知足的,可是性能上是不能接受的。
線上的交易功能平時各方面都很棒,節假日高峯期直接系統就癱瘓了。
那如何避免這些問題出如今生產上呢?
這就須要上線以前,首先作好對應的性能測試,避免再生產上出現問題,帶來嚴重的生產事故。
性能要高,性能要硬,性能測試,又高又硬!
作一件事情以前,咱們首先要肯定好本身的目標。
性能測試,到底要測試什麼?
有些相似於開發過程當中的需求分析,常見的測試指標以下。
響應時間是指某個請求或操做從發出到接收到反饋所消耗的時間,包括應用服務器(客戶端)處理時間、網絡傳輸時間以及數據庫服務器處理時間。
做爲用戶而言,在頁面點擊查詢,等待了多久才能獲取結果,這個就是響應時間。
用戶不關心你後端通過了多少個服務,慢就是原罪。
對於微服務系統,鏈路監控就顯得比較重要。能夠幫助咱們快速定位到底慢在哪裏。
TPS(Transaction Per Second)是指單位時間(每秒)系統處理的事務量。
我看網上還有不少相似的概念:點擊量/點擊率、吞吐量/吞吐率、PV/UV,這裏不作贅述。
我的看來本質上 TPS/QPS 就是去壓測你應用的極限,當訪問量較大的時候,程序可否活下來?
這裏主要涉及到兩個概念:高性能和高可用。
咱們後面會簡單討論下這兩點。
明確了測試指標以後,就須要進行測試的準備。
環境準備:好比你想壓測數據庫,那就須要準備對應配置的數據庫資源。
腳本的準備:數據初始化腳本,調用腳本等。
這個能夠類比開發過程當中的代碼開發。
ps: 性能壓測通常不是很經常使用,因此環境準備流程會比較長,這一點須要注意。
當進行測試以後,測試的結果必定要給出一份報告出來。
是否經過壓測要求?
最高的 QPS 是多少?
這樣開發能夠根據這份報告進行相應的優化。
提高性能的內容寫一本書也不爲過,這裏簡單羅列一些最經常使用的幾點:
(1)慢 SQL
通常程序若是響應時間較長,能夠首先看一下慢 SQL。
看下是否須要增長索引,或者進行 SQL 優化。
(2)緩存
針對查詢,性能提高最顯著的就是引入緩存。
固然,引入緩存會使架構變得複雜,這一點要結合本身的實際業務。
(3)硬件升級
若是程序優化的空間比較小,能夠考慮升級一下硬件資源。
好比服務器配置翻倍,數據庫配置翻倍。
什麼?你說公司沒錢升級?
沒錢升級作什麼壓測?
這個時候測試報告的做用就顯露了,直接用數聽說話。
直接說 QPS 達不到生產要求,程序優化的空間很小,推薦硬件升級配置,升級到多少。
作人,要以德服人。
作測試,要用數聽說話。
測試最經常使用的工具當屬 jmeter。
除此以外,還有一些其餘的工具:
LoadRunner、QALoad、SilkPerformer和Rational Performance Tester。
下面對幾個工具作下簡單介紹
Apache JMeter 能夠用於測試靜態和動態資源(Web動態應用程序)的性能。
它能夠用於模擬服務器、服務器組、網絡或對象上的負載,以測試其強度或分析不一樣負載類型下的整體性能。
將負載測試集成到開發工具中:IDE、jUnit、nUnit、Jenkins、Selenium和Microsoft Visual Studio。
從12.55版本開始,您能夠運行您的JMeter腳本,並在任何性能測試中集成JMeter和附加的腳本類型。
ps: 這個設計理念就很是好,能夠和成熟的工具進行整合。站在巨人的肩膀上。
QALoad是客戶/服務器系統、企業資源配置(ERP)和電子商務應用的自動化負載測試工具。
QALoad能夠模擬成百上千的用戶併發執行關鍵業務而完成對應用程序的測試,並針對所發現問題對系統性能進行優化,確保應用的成功部署。
ps: 這個工具本人沒有接觸過。
SilkPerformerV可讓你在使用前,就可以預測企業電子商務環境的行爲—不受電子商務應用規模和複雜性影響。
可視化的用戶化、負載條件下可視化的內容校驗、實時的性能監視和強大的管理報告能夠幫助您迅速將問題隔離,這樣,經過最小化測試周期、優化性能以及確保可伸縮性,加快了投入市場的時間,並保證了系統的可靠性。
做爲 DevOps 方法的一部分,IBM Rational Performance Tester 幫助軟件測試團隊更早、更頻繁地進行測試。
它驗證 Web 和服務器應用程序的可擴展性,肯定系統性能瓶頸的存在和緣由,並減小負載測試。
您的軟件測試團隊能夠快速執行性能測試,分析負載對應用程序的影響。
ps: 這一款工具備 IBM 提供,質量值得信賴。
這麼多工具可供使用,相信讀到這裏的小夥伴已經找到了本身心儀的測試工具。
別急,下面專門爲作 java 開發的小夥伴們推薦一款性能測試工具。
男人有男人的浪漫,開發者固然也要有開發者的浪漫。
【男人的浪.jpg】
做爲一名開發者,老馬平時單元測試使用 junit 最多。
因此一直但願找到一款基於 junit 的性能壓測工具,後來也確實找到了。
https://github.com/houbb/junitperf 是一款爲 java 開發者設計的性能測試框架。
能夠和 Junit5 完美契合。
使用簡單,便於項目開發過程當中的測試實用。
提供拓展,用戶可進行自定義開發。
支持 I18N
支持多種報告生成方式,支持自定義
Junt5 完美支持,便於 Java 開發者使用
<dependency> <groupId>com.github.houbb</groupId> <artifactId>junitperf</artifactId> <version>2.0.7</version> </dependency>
@JunitPerfConfig(duration = 1000) public void helloTest() throws InterruptedException { Thread.sleep(100); System.out.println("Hello Junit5"); }
@JunitPerfConfig
指定測試時的屬性配置。(必填項)
屬性 | 說明 | 類型 | 默認值 | 備註 |
---|---|---|---|---|
threads | 執行時使用多少線程執行 | int | 1 | |
warmUp | 準備時間 | long | 0 | 單位:毫秒 |
duration | 執行時間 | long | 60_000(1分鐘) | 單位:毫秒 |
latencyStatistics | 統計實現 | StatisticsCalculator | DefaultStatisticsCalculator | |
reporter | 報告實現 | Reporter | ConsoleReporter |
使用以下:
/** * 2個線程運行。 * 準備時間:1000ms * 運行時間: 2000ms * @throws InterruptedException if any */ @JunitPerfConfig(threads = 2, warmUp = 1000, duration = 2000) public void junitPerfConfigTest() throws InterruptedException { System.out.println("junitPerfConfigTest"); Thread.sleep(200); }
@JunitPerfRequire
指定測試時須要達到的要求。(選填項)
屬性 | 說明 | 類型 | 默認值 | 備註 |
---|---|---|---|---|
min | 最佳的運行耗時 | float | -1 | 最快的運行耗時若是高於這個值,則視爲失敗。單位:毫秒 |
max | 平均的運行耗時 | float | -1 | 最壞的運行耗時若是高於這個值,則視爲失敗。單位:毫秒 |
average | 平均的運行耗時 | float | -1 | 平均的運行耗時若是高於這個值,則視爲失敗。單位:毫秒 |
timesPerSecond | 每秒的最小執行次數 | int | 0 | 若是低於這個最小執行次數,則視爲失敗。 |
percentiles | 對於執行耗時的限定 | String[] | {} | percentiles={"20:220", "30:250"}。20% 的數據執行耗時不得超過 220ms;30% 的數據執行耗時不得超過 250ms; |
使用以下:
/** * 配置:2個線程運行。準備時間:1000ms。運行時間: 2000ms。 * 要求:最快不可低於 210ms, 最慢不得低於 250ms, 平均不得低於 225ms, 每秒運行次數不得低於 4 次。 * 20% 的數據不低於 220ms, 50% 的數據不得低於 230ms; * * @throws InterruptedException if any */ @JunitPerfConfig(threads = 2, warmUp = 1000, duration = 2000) @JunitPerfRequire(min = 210, max = 250, average = 225, timesPerSecond = 4, percentiles = {"20:220", "50:230"}) public void junitPerfConfigTest() throws InterruptedException { System.out.println("junitPerfConfigTest"); Thread.sleep(200); }
對應的測試報告生成方式也是多樣的,也容許用戶自定義。
基於控臺日志:
[INFO] [2020-06-16 20:05:53.618] [c.g.h.j.e.HelloWorldTest.helloTest] - Started at: 2020-06-16 20:05:52.512 [INFO] [2020-06-16 20:05:53.619] [c.g.h.j.e.HelloWorldTest.helloTest] - Invocations: 9 [INFO] [2020-06-16 20:05:53.620] [c.g.h.j.e.HelloWorldTest.helloTest] - Success: 9 [INFO] [2020-06-16 20:05:53.620] [c.g.h.j.e.HelloWorldTest.helloTest] - Errors: 0 [INFO] [2020-06-16 20:05:53.621] [c.g.h.j.e.HelloWorldTest.helloTest] - Thread Count: 1 [INFO] [2020-06-16 20:05:53.623] [c.g.h.j.e.HelloWorldTest.helloTest] - Warm up: 0ms [INFO] [2020-06-16 20:05:53.623] [c.g.h.j.e.HelloWorldTest.helloTest] - Execution time: 1000ms [INFO] [2020-06-16 20:05:53.624] [c.g.h.j.e.HelloWorldTest.helloTest] - Throughput: 9/s (Required: -1/s) - PASSED [INFO] [2020-06-16 20:05:53.625] [c.g.h.j.e.HelloWorldTest.helloTest] - Memory cost: 16byte [INFO] [2020-06-16 20:05:53.635] [c.g.h.j.e.HelloWorldTest.helloTest] - Min latency: 100.191414ms (Required: -1.0ms) - PASSED [INFO] [2020-06-16 20:05:53.635] [c.g.h.j.e.HelloWorldTest.helloTest] - Max latency: 105.2382ms (Required: -1.0ms) - PASSED [INFO] [2020-06-16 20:05:53.636] [c.g.h.j.e.HelloWorldTest.helloTest] - Avg latency: 101.43268ms (Required: -1.0ms) - PASSED
或者基於 HTML:
本文對性能測試作了最基本的介紹,讓小夥伴們對性能壓測有一個最基本的理解。
測試和開發同樣,都是一件費時費力,並且須要認真作才能作好的事情,其中的學問不是一篇就能說清的。
性能測試工具也比較多,本文重點介紹了專門爲 java 開發者打造的 junitperf 工具。
下一節咱們將從源碼角度,講解一下 junitperf 的實現原理。
我是老馬,期待與你的下次重逢。
開源地址:https://github.com/houbb/junitperf