From c0d7652524ebe5fe9345f874939c9a0d0d6554b5 Mon Sep 17 00:00:00 2001 From: yml2213 Date: Thu, 2 Jul 2026 12:21:05 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B5=8B=E8=AF=95-2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scripts/test-kuaishou-industry-http.ts | 59 ++++++++++++++----- docs/行业电子凭证/5.测试指南.md | 6 +- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/apps/backend/scripts/test-kuaishou-industry-http.ts b/apps/backend/scripts/test-kuaishou-industry-http.ts index bfc6d84c..48f5b8fb 100644 --- a/apps/backend/scripts/test-kuaishou-industry-http.ts +++ b/apps/backend/scripts/test-kuaishou-industry-http.ts @@ -246,7 +246,13 @@ const prepParams = buildSignedParams(appKey, { certActualStartTime: Date.now(), certActualEndTime: Date.now() + 30 * 24 * 60 * 60 * 1000, }, 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) { console.log('') @@ -256,16 +262,21 @@ for (const endpoint of endpointsToTest) { console.log('╚══════════════════════════════════════════════════════╝') 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.successes}`) - console.log(` 失败数 : ${result.failures}`) + console.log(` 业务成功 : ${result.successes}`) + console.log(` 业务失败 : ${result.bizErrors}${result.bizSample ? ` (示例: ${result.bizSample})` : ''}`) + console.log(` 被限流 : ${result.rateLimited}`) console.log(` 平均耗时 : ${result.avgMs.toFixed(1)} ms`) console.log(` P50 : ${result.p50Ms.toFixed(1)} ms`) console.log(` P95 : ${result.p95Ms.toFixed(1)} ms`) console.log(` P99 : ${result.p99Ms.toFixed(1)} ms`) console.log(` 最小耗时 : ${result.minMs.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('') @@ -315,10 +326,12 @@ async function runLoadTest( duration: number, oid: string, ): Promise<{ - actualTps: number + successTps: number totalReqs: number successes: number - failures: number + bizErrors: number + bizSample: string + rateLimited: number avgMs: number p50Ms: number p95Ms: number @@ -326,13 +339,14 @@ async function runLoadTest( minMs: number maxMs: number }> { - const interval = Math.max(1, Math.floor(1000 / tps)) - const totalRequests = Math.min(tps * duration, 10000) const latencies: number[] = [] let successes = 0 - let failures = 0 + let bizErrors = 0 + let rateLimited = 0 + let bizSample = '' const startedAt = Date.now() const deadline = startedAt + duration * 1000 + const intervalMs = Math.max(1, Math.floor(1000 / tps)) const worker = async () => { while (Date.now() < deadline) { @@ -360,17 +374,30 @@ async function runLoadTest( } 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) - if (ok || (endpoint === 'destroy-code' && ms < 500)) { + + if (ok) { 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 { - failures++ + bizErrors++ + if (!bizSample) { + bizSample = `HTTP ${ms}ms ${JSON.stringify(data).slice(0, 100)}` + } } const elapsed = Date.now() - startedReq - const sleep = interval - elapsed + const sleep = intervalMs - elapsed if (sleep > 0) { await delay(sleep) } @@ -384,10 +411,12 @@ async function runLoadTest( latencies.sort((a, b) => a - b) return { - actualTps: successes / Math.max(1, (Date.now() - startedAt) / 1000), + successTps: successes / Math.max(1, (Date.now() - startedAt) / 1000), totalReqs: latencies.length, successes, - failures, + bizErrors, + bizSample, + rateLimited, avgMs: avg(latencies), p50Ms: percentile(latencies, 50), p95Ms: percentile(latencies, 95), diff --git a/docs/行业电子凭证/5.测试指南.md b/docs/行业电子凭证/5.测试指南.md index 9b4dcfa2..9a9f7b54 100644 --- a/docs/行业电子凭证/5.测试指南.md +++ b/docs/行业电子凭证/5.测试指南.md @@ -27,7 +27,7 @@ npm run test:industry:http -- \ --signSecret=xxx # 远程 - 使用 .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 # 全部接口 100 TPS npm run test:industry:http -- \ - --baseUrl=https://order.khhao.com \ + --baseUrl=https://ks.khhao.com \ --load --tps=100 --duration=10 # 单接口 500 QPS npm run test:industry:http -- \ - --baseUrl=https://order.khhao.com \ + --baseUrl=https://ks.khhao.com \ --load --endpoint=query-code --tps=500 --duration=30 # 测试环境(自签证书)