Azure 負載測試會提供 JavaScript 中的用戶端連結庫給使用者,讓使用者可以原生與 Azure Load Testing 服務互動。 Azure 負載測試是完全受控的負載測試服務,可讓您產生大規模的負載。 不論應用程式的裝載位置為何,服務都會模擬應用程式的流量。 開發人員、測試人員和質量保證 (QA) 工程師可以使用它來優化應用程式效能、延展性或容量。
請高度依賴我們的 REST 用戶端檔, 使用此連結庫
文件
有各種文件可協助您開始使用
開始
目前支持的環境
先決條件
- 您必須擁有 Azure 訂用帳戶,並 Azure 負載測試服務資源 使用此套件。
安裝 @azure-rest/load-testing 套件
使用 npm安裝適用於 JavaScript 的 AzureLoadTesting 用戶端 REST 用戶端連結庫:
npm install @azure-rest/load-testing
建立及驗證 AzureLoadTesting 用戶端
若要使用 Azure Active Directory(AAD) 令牌認證,請提供從 @azure/identity 連結庫取得所需認證類型的實例。
若要向 AAD 進行驗證,您必須先 npm 安裝 @azure/identity
設定之後,您可以選擇要使用的 @azure/identity認證類型。
例如,DefaultAzureCredential 可用來驗證用戶端。
將 AAD 應用程式的用戶端識別碼、租使用者識別碼和客戶端密碼的值設定為環境變數:AZURE_CLIENT_ID、AZURE_TENANT_ID、AZURE_CLIENT_SECRET
import AzureLoadTesting, { AzureLoadTestingClient } from "@azure-rest/load-testing";
import { DefaultAzureCredential } from "@azure/identity";
const Client: AzureLoadTestingClient = AzureLoadTesting(Endpoint, new DefaultAzureCredential());
重要概念
下列元件組成 Azure 負載測試服務。 適用於 JavaScript 的 Azure 負載測試用戶端連結庫可讓您透過使用專用客戶端物件來與每個元件互動。
測試
測試會指定測試文本,以及執行負載測試的組態設定。 您可以在 Azure 負載測試資源中建立一或多個測試。
應用程式元件
當您針對 Azure 裝載的應用程式執行負載測試時,您可以監視不同 Azure 應用程式元件的資源計量(伺服器端計量)。 當負載測試執行時,以及在測試完成之後,您可以在 Azure 負載測試儀錶板中監視和分析資源計量。
指標
在負載測試期間,Azure 負載測試會收集測試執行的相關計量。 計量有兩種類型:
用戶端計量會提供測試引擎所報告的詳細數據。 這些計量包括虛擬用戶數目、要求回應時間、失敗要求數目,或每秒要求數目。
伺服器端計量適用於 Azure 裝載的應用程式,並提供 Azure 應用程式元件的相關信息。 計量可以用於資料庫讀取數目、HTTP 回應類型或容器資源耗用量。
測試引擎
測試引擎是執行 Apache JMeter 測試腳本的計算基礎結構。 您可以藉由設定測試引擎數目來相應放大負載測試。 測試腳本會跨指定的測試引擎數目平行執行。
試運轉
測試回合代表負載測試的一個執行。 它會收集與執行 Apache JMeter 腳本、負載測試 YAML 組態、要監視的應用程式元件清單,以及測試結果相關聯的記錄。
Data-Plane 端點
Azure 負載測試資源的數據平面可使用下列 URL 格式尋址:
00000000-0000-0000-0000-000000000000.aaa.cnt-prod.loadtesting.azure.com
第一個 GUID 00000000-0000-0000-0000-000000000000 是用來存取 Azure Load Testing 資源的唯一標識符。 後面接著 aaa,這是資源的 Azure 區域。
數據平面端點是從控制平面 API 取得。
範例:1234abcd-12ab-12ab-12ab-123456abcdef.eus.cnt-prod.loadtesting.azure.com
在上述範例中,eus 代表 Azure 區域 East US。
例子
建立負載測試
import { AzureLoadTestingClient } from "@azure-rest/load-testing";
import AzureLoadTesting from "@azure-rest/load-testing";
import { DefaultAzureCredential } from "@azure/identity";
var TEST_ID = "some-test-id";
var DISPLAY_NAME = "my-load-test";
const client: AzureLoadTestingClient = AzureLoadTesting("<Endpoint>", new DefaultAzureCredential());
await client.path("/tests/{testId}", TEST_ID).patch({
contentType: "application/merge-patch+json",
body: {
displayName: DISPLAY_NAME,
description: "",
loadTestConfiguration: {
engineInstances: 1,
splitAllCSVs: false,
},
secrets: {},
environmentVariables: {},
passFailCriteria: { passFailMetrics: {} },
},
});
將 .jmx 檔案上傳至測試
import { AzureLoadTestingClient, getLongRunningPoller, isUnexpected } from "@azure-rest/load-testing";
import AzureLoadTesting from "@azure-rest/load-testing";
import { DefaultAzureCredential } from "@azure/identity";
import { createReadStream } from "fs";
const client: AzureLoadTestingClient = AzureLoadTesting("<Endpoint>", new DefaultAzureCredential());
var TEST_ID = "some-test-id";
const readStream = createReadStream("./sample.jmx");
const fileUploadResult = await client
.path("/tests/{testId}/files/{fileName}", TEST_ID, "sample.jmx")
.put({
contentType: "application/octet-stream",
body: readStream,
});
if (isUnexpected(fileUploadResult)) {
throw fileUploadResult.body.error;
}
let fileValidateResult;
const fileValidatePoller = await getLongRunningPoller(client, fileUploadResult);
try{
fileValidateResult = await fileValidatePoller.pollUntilDone({
abortSignal: AbortSignal.timeout(120*1000), // timeout of 120 seconds
});} catch (ex: any) {
new Error("Error in polling file Validation" + ex.message); //polling timed out
}
if (fileValidatePoller.getOperationState().status != "succeeded" && fileValidateResult)
throw new Error(
"There is some issue in validation, please make sure uploaded file is a valid JMX." +
fileValidateResult.body.validationFailureDetails
);
執行測試和擷取計量
import { AzureLoadTestingClient, getLongRunningPoller, isUnexpected } from "@azure-rest/load-testing";
import AzureLoadTesting from "@azure-rest/load-testing";
import { DefaultAzureCredential } from "@azure/identity";
const client: AzureLoadTestingClient = AzureLoadTesting("<Endpoint>", new DefaultAzureCredential());
var TEST_ID = "some-test-id";
var DISPLAY_NAME = "my-load-test";
var TEST_RUN_ID = "some-test-run-id";
// Creating/Updating the test run
const testRunCreationResult = await client.path("/test-runs/{testRunId}", TEST_RUN_ID).patch({
contentType: "application/merge-patch+json",
body: {
testId: TEST_ID,
displayName: DISPLAY_NAME,
},
});
if (isUnexpected(testRunCreationResult)) {
throw testRunCreationResult.body.error;
}
if (testRunCreationResult.body.testRunId === undefined)
throw new Error("Test Run ID returned as undefined.");
const testRunPoller = await getLongRunningPoller(client, testRunCreationResult);
let testRunResult;
try {
testRunResult = await testRunPoller.pollUntilDone({
abortSignal: AbortSignal.timeout(60000), // timeout of 60 seconds
});
} catch (ex: any) {
new Error("Error in polling test run completion" + ex.message); //polling timed out
}
if (testRunPoller.getOperationState().status != "succeeded")
throw new Error("There is some issue in running the test, Error Response : " + testRunResult);
if (testRunResult) {
let testRunStarttime = testRunResult.body.startDateTime;
let testRunEndTime = testRunResult.body.endDateTime;
// get list of all metric namespaces and pick the first one
const metricNamespaces = await client
.path("/test-runs/{testRunId}/metric-namespaces", TEST_RUN_ID)
.get();
if (isUnexpected(metricNamespaces)) {
throw metricNamespaces.body.error;
}
const metricNamespace = metricNamespaces.body.value[0];
if (metricNamespace.name === undefined) {
throw "No Metric Namespace name is defined.";
}
// get list of all metric definitions and pick the first one
const metricDefinitions = await client
.path("/test-runs/{testRunId}/metric-definitions", TEST_RUN_ID)
.get({
queryParameters: {
metricNamespace: metricNamespace.name,
},
});
if (isUnexpected(metricDefinitions)) {
throw metricDefinitions.body.error;
}
const metricDefinition = metricDefinitions.body.value[0];
if (metricDefinition.name === undefined) {
throw "No Metric Namespace name is defined.";
}
// fetch client metrics using metric namespace and metric name
const metricsResult = await client.path("/test-runs/{testRunId}/metrics", TEST_RUN_ID).post({
queryParameters: {
metricname: metricDefinition.name,
metricNamespace: metricNamespace.name,
timespan: testRunStarttime + "/" + testRunEndTime,
},
});
console.log(metricsResult);
console.log(testRunResult);
}
故障排除
伐木
啟用記錄可能有助於找出有關失敗的實用資訊。 若要查看 HTTP 要求和回應的記錄,請將 AZURE_LOG_LEVEL 環境變數設定為 info。 或者,您可以在運行時間啟用記錄,方法是在 @azure/logger中呼叫 setLogLevel:
import { setLogLevel } from "@azure/logger";
setLogLevel("info");
如需如何啟用記錄的詳細指示,請參閱
後續步驟
Azure 載入測試 JavaScript SDK 範例可在 SDK 的 GitHub 存放庫中取得。 這些範例提供常見案例的範例程序代碼。
請參閱
貢獻
如需參與此存放庫的詳細資訊,請參閱 參與指南。
- 派生
- 建立您的功能分支 (
git checkout -b my-new-feature) - 認可您的變更 (
git commit -am 'Add some feature') - 推送至分支 (
git push origin my-new-feature) - 建立新的提取要求