如何快速排程 PTS 的百萬併發能力
作者:靈苒
在實際的業務場景中,壓測是必不可少的一環,無論是對伺服器、資料庫、網路等效能瓶頸的評估,還是如瀏覽、下單、支付等重要流量節點的業務連續性保障,亦或是搬站上雲整體業務穩定性的預估,這些都需要效能壓測來幫助你建立對系統和業務的完整認知。根據 Google 的統計,如果網站開啟慢每 500 毫秒,使用者訪問量將下降 20%。根據 Amazon 統計,每慢 100 毫秒,交易額下降 1%。這些事件和統計資料為大家敲響了警鐘,也客觀說明了效能壓測對於企業應用的重要性。
壓測是通過模擬使用者行為對業務系統發起請求,測算出系統的承載能力,並對系統做一次全面的體檢,壓測後可根據壓測表現優化系統瓶頸,防止出現線上故障。
業界常見的壓測軟體 JMeter 和 PTS
目前 JMeter 是效能壓測領域應用最廣泛的開源軟體。
對於場景簡單,要求測試併發量不高的情況下,JMeter 本地測試就能滿足需求。但隨著網際網路使用者的增加,對系統承載更大併發的需求日漸提升,而單臺 JMeter 施壓機的施壓能力有一定上限,所以需要使用多臺施壓機,以提高 JMeter 的施壓能力,這就要使用到 JMeter 的分散式施壓功能。
但 JMeter 的分散式壓測前置準備較多,需要注意以下幾點:
- 施壓機的防火牆已關閉或打開了正確的埠。為 RMI 設定了 SSL 或禁用了它。
- 所有施壓機都在同一個子網上。如果使用 192.xxx或10.xxx IP 地址,則伺服器位於同一子網中。
- 所有施壓機上使用相同版本的 JMeter 和 Java。
- 所有施壓機都已經拷貝了切分好的 CSV 資料檔案、依賴 jar 包等。
- 已配置好監控資料的收集。
由此可見 JMeter 的分散式壓測需要自己協調各資源,前置準備比較麻煩,對實施壓測的人員來說壓測效率低。
PTS 是阿里雲研發的效能測試工具,最初主要為了模擬雙十一流量洪峰,如今已走過十個年頭,在場景編排、壓測執行、壓測監控分析、報告總結等各方面能力相對完善,可提供百萬併發、千萬 TPS 流量發起能力,並且還能完全相容 JMeter,可天然彌補 JMeter 在效能壓測中的劣勢。對使用 JMerer 無法繞過叢集問題的使用者是一個很好的選擇。
PTS 的 JMeter 壓測極大的簡化了 JMeter 分散式壓測流程,同時也降低了壓測過程中對施壓機的維護成本。使用 PTS 的 JMeter 壓測,使用者只需要在控制檯配置需要使用的機器數,無須使用者提前準備多臺已安裝相同 Java 和 JMeter 版本的施壓機。同時無須使用者根據施壓機數量去切分 CSV 引數檔案;壓測結束後,PTS 會將監控資料彙總產生一個詳細的壓測報告供使用者查閱。
相比於直接在命令列執行 JMeter 指令碼來說,PTS 使用更加方便,可按需提供海量的施壓能力,並且能提供簡潔直觀的監控和報告。
如何發起 PTS 的 JMeter 壓測
和所有壓測的核心步驟一樣,使用 PTS 的 JMeter 壓測,也主要集中在建立場景、壓測場景和檢視報告三個步驟中。
1、建立場景:PTS 的 JMeter 壓測以場景為核心,壓測物件為一個場景,場景中包括JMeter(原生)指令碼、JMeter 依賴(一系列依賴 jar 包和一系列 properties 配置)、及一些壓測配置(PTS 壓測的配置,例如公網/VPC 壓測、併發量、引擎數量、壓測時長等)。
2、壓測場景:對場景的操作分為兩方面,一是對場景配置的增刪改查,二是對場景的壓測和除錯。
3、生成報告:每次對場景壓測都會生成一個壓測任務,同時生成一個報告,其中包括壓測的關鍵指標,如 TPS、RT、成功率等,可輔助使用者排查系統性能瓶頸。此外,PTS 預設將報告儲存 30 天,可以隨時檢視歷史報告,並且提供匯出 PDF 格式的報告。
在壓測領域,隨著壓測需求日益多樣化,更多使用者希望將雲上的壓測能力繼承到自己的系統,或者根據自己的業務系統,編排自定義的壓測平臺,從而實現自動化定製化壓測需求。
所以,為了方便使用者便捷排程 PTS 百萬併發的能力,PTS 開通了 JMeter 的 OpenAPI,提供瞭如下幾類壓測的核心功能:編輯場景、除錯場景、壓測場景、檢視執行時資料、檢視報告。
通過整合 OpenAPI,客戶可以更加方便的在自己的業務場景實現 PTS 百萬級併發壓測的能力,實現場景的增、刪、改、查等各種操作,一鍵啟動壓測,並在壓測過程中,隨時停止壓測。同時生成的壓測報告中,除了JMeter 原生的日誌外,還有 PTS 針對某個取樣器的成功率、TPS、RT 指標的聚合資料。另外還可以對報告進行檢視報告列表、JMeter 原生日誌以及 PTS 對 JMeter 取樣器壓測指標的聚合資料等功能。
那麼還等什麼呢?來,試著用 PTS 中 JMeter 的 OpenAPI 寫一個屬於你的百萬級併發壓測能力的壓測平臺吧!
附錄:
具體步驟如下
引入 pom 依賴
<!--建立PTS場景需要的實體類,如果只使用JMeter壓測則不需要引入-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>pts-api-entity</artifactId>
<version>1.0.1</version>
</dependency>
<!--PTS Java SDK依賴。-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>pts20201020</artifactId>
<version>1.8.10</version>
</dependency>
<!--阿里雲核心庫。-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.5.2</version>
</dependency>
\
複製下列程式碼
import com.aliyun.pts20201020.Client;
import com.aliyun.pts20201020.models.*;
import com.aliyun.teaopenapi.models.Config;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class StartingDemo {
public static void main(String[] args) throws Exception {
Client client = getClient();
// 建立場景
String sceneId = createScene(client);
// 啟動場景
String reportId = startTesting(client, sceneId);
// 最多等待次數
int count = 0;
// 查詢是否已生成報告
while (!hasReport(client, reportId) && count++ < 20) {
// 若報告還未生成,則等待(30s)一段時間再查詢
// 根據壓測時間酌情等待
Thread.sleep(30 * 1000);
}
// 檢視報告
getJMeterReport(client, reportId);
}
private static boolean hasReport(Client client, String reportId) throws Exception {
ListJMeterReportsRequest request = new ListJMeterReportsRequest();
// 分頁設定
request.setPageNumber(1);
request.setPageSize(1);
// 查詢條件設定
request.setReportId(reportId);
ListJMeterReportsResponse response = client.listJMeterReports(request);
return response.getBody().getReports().size() > 0;
}
private static void getJMeterReport(Client client, String reportId) throws Exception {
// 檢視機器日誌
GetJMeterLogsResponse getJMeterLogsResponse = getJMeterLogs(client, reportId);
List<Map<String, ?>> logs = getJMeterLogsResponse.getBody().getLogs();
// 檢視取樣器聚合資料
GetJMeterSampleMetricsResponse getJMeterSampleMetrics = getJMeterSampleMetrics(client, reportId);
List<String> sampleMetricList = getJMeterSampleMetrics.getBody().getSampleMetricList();
// 檢視取樣日誌
GetJMeterSamplingLogsResponse getJMeterSamplingLogs = getJMeterSamplingLogs(client, reportId);
List<String> sampleResults = getJMeterSamplingLogs.getBody().getSampleResults();
}
private static GetJMeterSamplingLogsResponse getJMeterSamplingLogs(Client client, String reportId) throws Exception {
GetJMeterSamplingLogsRequest request = new GetJMeterSamplingLogsRequest();
// 分頁設定
request.setPageNumber(1);
request.setPageSize(10);
// 條件設定
request.setReportId(reportId);
GetJMeterSamplingLogsResponse response = client.getJMeterSamplingLogs(request);
return response;
}
private static GetJMeterSampleMetricsResponse getJMeterSampleMetrics(Client client, String reportId) throws Exception {
GetJMeterSampleMetricsRequest request = new GetJMeterSampleMetricsRequest();
// 設定報告id
request.setReportId(reportId);
GetJMeterSampleMetricsResponse response = client.getJMeterSampleMetrics(request);
return response;
}
private static GetJMeterLogsResponse getJMeterLogs(Client client, String reportId) throws Exception {
GetJMeterLogsRequest request = new GetJMeterLogsRequest();
// 分頁設定
request.setPageNumber(1);
request.setPageSize(10);
// 查詢的壓測引擎索引
request.setReportId(reportId);
GetJMeterLogsResponse response = client.getJMeterLogs(request);
return response;
}
private static String startTesting(Client client, String sceneId) throws Exception {
StartTestingJMeterSceneResponse startTestingSceneResponse = startTestingScene(client, sceneId);
String reportId = startTestingSceneResponse.getBody().getReportId();
return reportId;
}
private static StartTestingJMeterSceneResponse startTestingScene(Client client, String sceneId) throws Exception {
StartTestingJMeterSceneRequest request = new StartTestingJMeterSceneRequest();
request.setSceneId(sceneId);
StartTestingJMeterSceneResponse response = client.startTestingJMeterScene(request);
return response;
}
private static String createScene(Client client) throws Exception {
SaveOpenJMeterSceneRequest request = new SaveOpenJMeterSceneRequest();
// 定義場景
SaveOpenJMeterSceneRequest.SaveOpenJMeterSceneRequestOpenJMeterScene scene = new SaveOpenJMeterSceneRequest.SaveOpenJMeterSceneRequestOpenJMeterScene();
// 設定場景名
scene.setSceneName("test");
// 設定檔案列表,包括JMeter指令碼、JMeter壓測依賴jar包、配置額度資料檔案等
List<SaveOpenJMeterSceneRequest.SaveOpenJMeterSceneRequestOpenJMeterSceneFileList> fileList = new ArrayList<SaveOpenJMeterSceneRequest.SaveOpenJMeterSceneRequestOpenJMeterSceneFileList>();
// 設定檔案的屬性 需要設定檔案的名稱和檔案公網可訪問的oss地址
SaveOpenJMeterSceneRequest.SaveOpenJMeterSceneRequestOpenJMeterSceneFileList testFile = new SaveOpenJMeterSceneRequest.SaveOpenJMeterSceneRequestOpenJMeterSceneFileList();
testFile.setFileName("baidu.jmx");
testFile.setFileOssAddress("http://pts-openapi-test.oss-cn-shanghai.aliyuncs.com/baidu.jmx");
fileList.add(testFile);
scene.setFileList(fileList);
// 設定場景併發,可設定為100萬
scene.setConcurrency(1000000);
// 設定引擎數量 說明:一臺引擎最多能發500併發,最少1併發所以此處能設定的引擎數為[2,1000],另外引擎數量越多消耗vum越快
scene.setAgentCount(2000);
// 設定壓測持續時間 60s
scene.setDuration(60);
// 設定測試檔案的名稱,這個檔案需包括在檔案列表中
scene.setTestFile("baidu.jmx");
request.setOpenJMeterScene(scene);
SaveOpenJMeterSceneResponse response = client.saveOpenJMeterScene(request);
return response.getBody().getSceneId();
}
private static Client getClient() throws Exception {
// 填寫自己的AK/SK
String accessKeyId = "ak";
String accessKeySecret = "sk";
Config config = new Config();
config.setAccessKeyId(accessKeyId);
config.setAccessKeySecret(accessKeySecret);
Client client = new Client(config);
return client;
}
}
填寫自己的 ak/sk
在上述程式碼的 getClient 中填寫正確的 ak/sk
點選啟動
點選 main 方法啟動
點選此處,前往 PTS 官網瞭解更多詳情!
- 阿里巴巴雲原生大資料運維平臺 SREWorks 正式開源
- 從“預見”到“遇見” | SAE 引領應用步入 Serverless 全託管新時代
- 阿里雲首家通過《可信雲·雲成本優化工具能力要求》評估,雲原生企業 IT 成本治理方案助力企業 FinOps 落地
- 成本節省 50%,10 人團隊使用函式計算開發 wolai 線上文件應用
- 阿里巴巴在 Envoy Gateway 的演進歷程淺析
- Nacos 開源之夏 2022 來了
- 記一次 JMeter 壓測 HTTPS 效能問題
- 雲釘一體:EventBridge 聯合釘釘聯結器打通雲釘生態
- Seata 企業版正式開放公測
- “暈乎乎的概念”:阿里雲函式計算的“應用”又是個啥
- 零元嚐鮮|阿里雲 Grafana 商業化服務正式釋出
- “暈乎乎的概念”:阿里雲函式計算的“應用”又是個啥
- 三大特性,多個場景,Serverless 應用引擎 SAE 全面升級
- Seata x 2022 開源之夏 ,一起來做開源達人!
- 雲釘一體:EventBridge 聯合釘釘聯結器打通雲釘生態
- 全面提升易用性:OpenClusterManagement 0.7 版本釋出
- 如何使用阿里雲 CDN 對部署在函式計算上的靜態網站進行快取
- ApacheCon Asia 2022 強勢來襲!16 大專題等你投稿!
- 淺析微服務全鏈路灰度解決方案
- 作業幫線上業務 Kubernetes Serverless 虛擬節點大規模應用實踐