你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
适用于 JavaScript 的 Azure 负载测试客户端库 - 版本 1.0.0
Azure 负载测试向用户提供 JavaScript 中的客户端库,用户可以通过该库与 Azure 负载测试服务进行本机交互。 Azure 负载测试是一项完全托管的负载测试服务,可用于生成大规模负载。 该服务可以模拟应用程序的流量,且无需其托管位置。 开发人员、测试人员和质量保证 (QA) 工程师可以使用该服务来优化应用程序性能、可缩放性或容量。
请严重依赖 REST 客户端文档 来使用此库
文档
提供了各种文档来帮助你入门
入门
目前支持的环境
- Node.js版本 14.x.x 或更高版本
先决条件
- 必须具有 Azure 订阅和 Azure 负载测试服务资源才能使用此包。
安装 @azure-rest/load-testing
包
使用 npm
安装适用于 JavaScript 的 AzureLoadTesting 客户端 REST 客户端库:
npm install @azure-rest/load-testing
创建客户端并对其进行身份验证AzureLoadTesting
若要使用 Azure Active Directory (AAD) 令牌凭据,请提供从 @azure/标识 库获取的所需凭据类型的实例。
若要使用 AAD 进行身份验证,必须先 npm
安装 @azure/identity
设置后,可以选择要使用的@azure/identity
凭据类型。
例如, DefaultAzureCredential 可用于对客户端进行身份验证。
将 AAD 应用程序的客户端 ID、租户 ID 和客户端密码的值设置为环境变量: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 负载测试资源的唯一标识符。 接下来 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 { AbortController } from "@azure/abort-controller";
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: AbortController.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";
import { AbortController } from "@azure/abort-controller";
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: AbortController.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/logger 包文档。
后续步骤
可在 SDK 的 GitHub 存储库中获取 Azure 加载测试 JavaScript SDK 示例。 这些示例为经常遇到的其他方案提供了示例代码。
请参阅 Azure 负载测试示例。
供稿
有关参与此存储库的详细信息,请参阅 参与指南。
- 分叉它
- 创建功能分支 (
git checkout -b my-new-feature
) - ()
git commit -am 'Add some feature'
提交更改 - 推送到分支 (
git push origin my-new-feature
) - 创建新的拉取请求