目錄
1、創建一個Spring Boot程序
@RestController
public class GcTestController {
@RequestMapping("/greeting/last/{seconds}")
public Greeting greeting(@PathVariable long seconds) {
try{
Thread.sleep(seconds*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Greeting greeting = new Greeting("Hello world!");
return greeting;
}
}
class Greeting{
private String message;
public Greeting(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
備註:服務端程序根據請求參數中的seconds,先停頓一定時長,然後才返回請求。目的:模擬服務端延遲
2、加大tomcat的最大線程數
#修改springboot配置文件application.properties
#tomcat server可開啓最大線程數
server.tomcat.max-threads=1000
3、使用JMeter加壓
創建100個線程,循環次數選永遠,設置HTTP請求響應timeout爲1000毫秒,因爲每個線程在收到響應後纔會發起下一次請求。設置1000毫秒,方便JMeter以固定吞吐量加壓。分以下階段加壓,第一階段請求參數爲/greeting/last/2,第二階段請求參數爲/greeting/last/6,第三階段請求參數爲/greeting/last/8
4、監控工具顯示
visual vm
jconsole
現象:
線程逐漸增多,堆內存消耗隨之增加,但cpu佔用率變化不大。線程增多是因爲三個階段每個請求停留時間爲2、6、8秒,JMeter有100個線程發送請求,每個請求等待一秒鐘就發送第二個請求,所以三個階段的併發量是200、600、800,各需要tomcat提供200、400、800個線程去處理迎戰同時到達的請求。cpu佔用率沒有加大的原因,是因爲服務的吞吐量沒有增大。這個最後解釋。
分析:
線程飆升,內存增大,cpu佔用率不變,吞吐量不變,這個時候要懷疑是不是web服務依賴的下游服務出現異常,導致響應時間變長。
定位問題:
瓶頸在哪個方法呢
visual vm監控
jconsole
通過visual vm抽樣器分析cpu的情況,我們得知是greeting方法佔用大量cpu時間,greeting隨着請求參數的變大,sleep時間增長,導致響應越來越慢。例如實際開發過程中,有時會遇到這樣的情況,隨着數據的增多,由於索引設計不合理,導致數據庫服務響應時間增長,進而web服務請求響應時間增長,請求處理不過來,導致tomcat開啓更多線程,但是吞吐量卻沒有提升。
概念再理解:
系統吞吐量幾個重要參數:QPS(TPS)、併發數、響應時間
QPS(TPS):每秒鐘request/事務 數量
併發數: 系統同時處理的request/事務數
響應時間: 一般取平均響應時間
它們之間的關係:
吞吐量QPS(TPS)= 併發數/平均響應時間
所以實例中的吞吐量幾乎不變得原因是,計算如下表
請求參數seconds | 併發數 | 平均響應時間 |
2 | 200 | 2 |
6 | 600 | 6 |
8 | 800 | 8 |
jconsole關於吞吐量的tip
MBean:maxTime每個請求最長處理時間。requestCount總共處理完成的請求數量。processingTime處理這些請求總共花費的時間。