增加测试-2
This commit is contained in:
@@ -246,7 +246,13 @@ const prepParams = buildSignedParams(appKey, {
|
|||||||
certActualStartTime: Date.now(),
|
certActualStartTime: Date.now(),
|
||||||
certActualEndTime: Date.now() + 30 * 24 * 60 * 60 * 1000,
|
certActualEndTime: Date.now() + 30 * 24 * 60 * 60 * 1000,
|
||||||
}, signMethod)
|
}, signMethod)
|
||||||
await post('/send-code', prepParams, {})
|
const prepResult = await post('/send-code', prepParams, {})
|
||||||
|
if (prepResult.data?.result === 1) {
|
||||||
|
console.log(` 数据准备完成 (${prepResult.ms}ms)`)
|
||||||
|
} else {
|
||||||
|
console.log(` ⚠ 数据准备失败: result=${prepResult.data?.result} error_msg="${prepResult.data?.error_msg}" (${prepResult.ms}ms)`)
|
||||||
|
console.log(` 请确认服务端已配置正确的 appKey/signSecret 且未触发限流`)
|
||||||
|
}
|
||||||
|
|
||||||
for (const endpoint of endpointsToTest) {
|
for (const endpoint of endpointsToTest) {
|
||||||
console.log('')
|
console.log('')
|
||||||
@@ -256,16 +262,21 @@ for (const endpoint of endpointsToTest) {
|
|||||||
console.log('╚══════════════════════════════════════════════════════╝')
|
console.log('╚══════════════════════════════════════════════════════╝')
|
||||||
|
|
||||||
const result = await runLoadTest(endpoint, targetTps, testDuration, loadTestOid)
|
const result = await runLoadTest(endpoint, targetTps, testDuration, loadTestOid)
|
||||||
console.log(` 实际 TPS : ${result.actualTps.toFixed(1)}`)
|
console.log(` 成功 TPS : ${result.successTps.toFixed(1)} (业务 result=1)`)
|
||||||
console.log(` 总请求数 : ${result.totalReqs}`)
|
console.log(` 总请求数 : ${result.totalReqs}`)
|
||||||
console.log(` 成功数 : ${result.successes}`)
|
console.log(` 业务成功 : ${result.successes}`)
|
||||||
console.log(` 失败数 : ${result.failures}`)
|
console.log(` 业务失败 : ${result.bizErrors}${result.bizSample ? ` (示例: ${result.bizSample})` : ''}`)
|
||||||
|
console.log(` 被限流 : ${result.rateLimited}`)
|
||||||
console.log(` 平均耗时 : ${result.avgMs.toFixed(1)} ms`)
|
console.log(` 平均耗时 : ${result.avgMs.toFixed(1)} ms`)
|
||||||
console.log(` P50 : ${result.p50Ms.toFixed(1)} ms`)
|
console.log(` P50 : ${result.p50Ms.toFixed(1)} ms`)
|
||||||
console.log(` P95 : ${result.p95Ms.toFixed(1)} ms`)
|
console.log(` P95 : ${result.p95Ms.toFixed(1)} ms`)
|
||||||
console.log(` P99 : ${result.p99Ms.toFixed(1)} ms`)
|
console.log(` P99 : ${result.p99Ms.toFixed(1)} ms`)
|
||||||
console.log(` 最小耗时 : ${result.minMs.toFixed(1)} ms`)
|
console.log(` 最小耗时 : ${result.minMs.toFixed(1)} ms`)
|
||||||
console.log(` 最大耗时 : ${result.maxMs.toFixed(1)} ms`)
|
console.log(` 最大耗时 : ${result.maxMs.toFixed(1)} ms`)
|
||||||
|
|
||||||
|
if (result.rateLimited > result.totalReqs * 0.1) {
|
||||||
|
console.log(` ⚠ 注意: ${((result.rateLimited / result.totalReqs) * 100).toFixed(0)}% 请求被限流,建议调高 KUASHOU_INDUSTRY_RATE_LIMIT_MAX`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('')
|
console.log('')
|
||||||
@@ -315,10 +326,12 @@ async function runLoadTest(
|
|||||||
duration: number,
|
duration: number,
|
||||||
oid: string,
|
oid: string,
|
||||||
): Promise<{
|
): Promise<{
|
||||||
actualTps: number
|
successTps: number
|
||||||
totalReqs: number
|
totalReqs: number
|
||||||
successes: number
|
successes: number
|
||||||
failures: number
|
bizErrors: number
|
||||||
|
bizSample: string
|
||||||
|
rateLimited: number
|
||||||
avgMs: number
|
avgMs: number
|
||||||
p50Ms: number
|
p50Ms: number
|
||||||
p95Ms: number
|
p95Ms: number
|
||||||
@@ -326,13 +339,14 @@ async function runLoadTest(
|
|||||||
minMs: number
|
minMs: number
|
||||||
maxMs: number
|
maxMs: number
|
||||||
}> {
|
}> {
|
||||||
const interval = Math.max(1, Math.floor(1000 / tps))
|
|
||||||
const totalRequests = Math.min(tps * duration, 10000)
|
|
||||||
const latencies: number[] = []
|
const latencies: number[] = []
|
||||||
let successes = 0
|
let successes = 0
|
||||||
let failures = 0
|
let bizErrors = 0
|
||||||
|
let rateLimited = 0
|
||||||
|
let bizSample = ''
|
||||||
const startedAt = Date.now()
|
const startedAt = Date.now()
|
||||||
const deadline = startedAt + duration * 1000
|
const deadline = startedAt + duration * 1000
|
||||||
|
const intervalMs = Math.max(1, Math.floor(1000 / tps))
|
||||||
|
|
||||||
const worker = async () => {
|
const worker = async () => {
|
||||||
while (Date.now() < deadline) {
|
while (Date.now() < deadline) {
|
||||||
@@ -360,17 +374,30 @@ async function runLoadTest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const params = buildSignedParams(appKey, bizParams, signMethod)
|
const params = buildSignedParams(appKey, bizParams, signMethod)
|
||||||
const { ok, ms } = await post(`/${endpoint}`, params, { oid })
|
const { ok, data, ms } = await post(`/${endpoint}`, params, { oid })
|
||||||
|
|
||||||
latencies.push(ms)
|
latencies.push(ms)
|
||||||
if (ok || (endpoint === 'destroy-code' && ms < 500)) {
|
|
||||||
|
if (ok) {
|
||||||
successes++
|
successes++
|
||||||
|
} else if (data?.error_msg && String(data.error_msg).includes('频繁')) {
|
||||||
|
rateLimited++
|
||||||
|
} else if (data?.result === 4010003 && String(data?.error_msg || '').includes('频繁')) {
|
||||||
|
rateLimited++
|
||||||
|
} else if (data?.result != null && data?.result !== 1) {
|
||||||
|
bizErrors++
|
||||||
|
if (!bizSample) {
|
||||||
|
bizSample = `result=${data.result} "${data.error_msg}"`
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
failures++
|
bizErrors++
|
||||||
|
if (!bizSample) {
|
||||||
|
bizSample = `HTTP ${ms}ms ${JSON.stringify(data).slice(0, 100)}`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const elapsed = Date.now() - startedReq
|
const elapsed = Date.now() - startedReq
|
||||||
const sleep = interval - elapsed
|
const sleep = intervalMs - elapsed
|
||||||
if (sleep > 0) {
|
if (sleep > 0) {
|
||||||
await delay(sleep)
|
await delay(sleep)
|
||||||
}
|
}
|
||||||
@@ -384,10 +411,12 @@ async function runLoadTest(
|
|||||||
latencies.sort((a, b) => a - b)
|
latencies.sort((a, b) => a - b)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
actualTps: successes / Math.max(1, (Date.now() - startedAt) / 1000),
|
successTps: successes / Math.max(1, (Date.now() - startedAt) / 1000),
|
||||||
totalReqs: latencies.length,
|
totalReqs: latencies.length,
|
||||||
successes,
|
successes,
|
||||||
failures,
|
bizErrors,
|
||||||
|
bizSample,
|
||||||
|
rateLimited,
|
||||||
avgMs: avg(latencies),
|
avgMs: avg(latencies),
|
||||||
p50Ms: percentile(latencies, 50),
|
p50Ms: percentile(latencies, 50),
|
||||||
p95Ms: percentile(latencies, 95),
|
p95Ms: percentile(latencies, 95),
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ npm run test:industry:http -- \
|
|||||||
--signSecret=xxx
|
--signSecret=xxx
|
||||||
|
|
||||||
# 远程 - 使用 .env 中的密钥
|
# 远程 - 使用 .env 中的密钥
|
||||||
npm run test:industry:http -- --baseUrl=https://order.khhao.com
|
npm run test:industry:http -- --baseUrl=https://ks.khhao.com
|
||||||
```
|
```
|
||||||
|
|
||||||
测试内容:发码 → 幂等性 → 查询全部 → 查询单个 → 不存在订单 → 销毁 → 销毁验证 → 整单销毁 → 签名错误拦截
|
测试内容:发码 → 幂等性 → 查询全部 → 查询单个 → 不存在订单 → 销毁 → 销毁验证 → 整单销毁 → 签名错误拦截
|
||||||
@@ -37,12 +37,12 @@ npm run test:industry:http -- --baseUrl=https://order.khhao.com
|
|||||||
```bash
|
```bash
|
||||||
# 全部接口 100 TPS
|
# 全部接口 100 TPS
|
||||||
npm run test:industry:http -- \
|
npm run test:industry:http -- \
|
||||||
--baseUrl=https://order.khhao.com \
|
--baseUrl=https://ks.khhao.com \
|
||||||
--load --tps=100 --duration=10
|
--load --tps=100 --duration=10
|
||||||
|
|
||||||
# 单接口 500 QPS
|
# 单接口 500 QPS
|
||||||
npm run test:industry:http -- \
|
npm run test:industry:http -- \
|
||||||
--baseUrl=https://order.khhao.com \
|
--baseUrl=https://ks.khhao.com \
|
||||||
--load --endpoint=query-code --tps=500 --duration=30
|
--load --endpoint=query-code --tps=500 --duration=30
|
||||||
|
|
||||||
# 测试环境(自签证书)
|
# 测试环境(自签证书)
|
||||||
|
|||||||
Reference in New Issue
Block a user