278 lines
7.7 KiB
TypeScript
278 lines
7.7 KiB
TypeScript
|
|
/**
|
|||
|
|
* [OP-ST004] 多商户性能测试服务
|
|||
|
|
* @description 测试多商户系统的性能,分析并发情况下的系统表现
|
|||
|
|
* @version 1.0
|
|||
|
|
*/
|
|||
|
|
export class MerchantPerformanceTest {
|
|||
|
|
/**
|
|||
|
|
* 执行多商户性能测试
|
|||
|
|
* @param params 测试参数
|
|||
|
|
* @param traceInfo 追踪信息
|
|||
|
|
* @returns 性能测试结果
|
|||
|
|
*/
|
|||
|
|
public static async runPerformanceTest(params: {
|
|||
|
|
concurrentMerchants: number;
|
|||
|
|
testDuration: number; // 测试持续时间(秒)
|
|||
|
|
operationsPerSecond: number;
|
|||
|
|
}, traceInfo: {
|
|||
|
|
tenantId: string;
|
|||
|
|
shopId: string;
|
|||
|
|
taskId: string;
|
|||
|
|
traceId: string;
|
|||
|
|
businessType: 'TOC' | 'TOB';
|
|||
|
|
}): Promise<{
|
|||
|
|
testId: string;
|
|||
|
|
startTime: string;
|
|||
|
|
endTime: string;
|
|||
|
|
concurrentMerchants: number;
|
|||
|
|
operationsPerSecond: number;
|
|||
|
|
results: {
|
|||
|
|
averageResponseTime: number;
|
|||
|
|
throughput: number;
|
|||
|
|
errorRate: number;
|
|||
|
|
maxResponseTime: number;
|
|||
|
|
p95ResponseTime: number;
|
|||
|
|
p99ResponseTime: number;
|
|||
|
|
};
|
|||
|
|
}> {
|
|||
|
|
// 生成测试ID
|
|||
|
|
const testId = `PT-${Date.now()}`;
|
|||
|
|
const startTime = new Date().toISOString();
|
|||
|
|
|
|||
|
|
// 模拟性能测试过程
|
|||
|
|
console.log(`[MerchantPerformanceTest] 开始性能测试 - ID: ${testId}, 并发商户数: ${params.concurrentMerchants}`, {
|
|||
|
|
...traceInfo,
|
|||
|
|
testId
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 模拟测试执行
|
|||
|
|
await new Promise(resolve => setTimeout(resolve, params.testDuration * 1000));
|
|||
|
|
|
|||
|
|
// 生成模拟性能数据
|
|||
|
|
const responseTimes: number[] = [];
|
|||
|
|
for (let i = 0; i < params.concurrentMerchants * params.operationsPerSecond * params.testDuration; i++) {
|
|||
|
|
// 生成正态分布的响应时间
|
|||
|
|
const responseTime = this.generateNormalDistribution(150, 50);
|
|||
|
|
responseTimes.push(responseTime);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 计算性能指标
|
|||
|
|
responseTimes.sort((a, b) => a - b);
|
|||
|
|
const totalOperations = responseTimes.length;
|
|||
|
|
const errorCount = Math.floor(totalOperations * 0.01); // 1% 错误率
|
|||
|
|
|
|||
|
|
const results = {
|
|||
|
|
averageResponseTime: responseTimes.reduce((sum, time) => sum + time, 0) / responseTimes.length,
|
|||
|
|
throughput: totalOperations / params.testDuration,
|
|||
|
|
errorRate: errorCount / totalOperations,
|
|||
|
|
maxResponseTime: Math.max(...responseTimes),
|
|||
|
|
p95ResponseTime: responseTimes[Math.floor(responseTimes.length * 0.95)],
|
|||
|
|
p99ResponseTime: responseTimes[Math.floor(responseTimes.length * 0.99)]
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const endTime = new Date().toISOString();
|
|||
|
|
|
|||
|
|
// 记录测试完成日志
|
|||
|
|
console.log(`[MerchantPerformanceTest] 性能测试完成 - ID: ${testId}, 吞吐量: ${results.throughput.toFixed(2)} ops/s`, {
|
|||
|
|
...traceInfo,
|
|||
|
|
testId,
|
|||
|
|
results
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
testId,
|
|||
|
|
startTime,
|
|||
|
|
endTime,
|
|||
|
|
concurrentMerchants: params.concurrentMerchants,
|
|||
|
|
operationsPerSecond: params.operationsPerSecond,
|
|||
|
|
results
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 生成正态分布的随机数
|
|||
|
|
* @param mean 均值
|
|||
|
|
* @param stdDev 标准差
|
|||
|
|
* @returns 随机数
|
|||
|
|
*/
|
|||
|
|
private static generateNormalDistribution(mean: number, stdDev: number): number {
|
|||
|
|
let u = 0, v = 0;
|
|||
|
|
while (u === 0) u = Math.random();
|
|||
|
|
while (v === 0) v = Math.random();
|
|||
|
|
const num = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v);
|
|||
|
|
return Math.max(0, mean + num * stdDev);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 生成性能报告
|
|||
|
|
* @param testId 测试ID
|
|||
|
|
* @param traceInfo 追踪信息
|
|||
|
|
* @returns 性能报告
|
|||
|
|
*/
|
|||
|
|
public static async generatePerformanceReport(testId: string, traceInfo: {
|
|||
|
|
tenantId: string;
|
|||
|
|
shopId: string;
|
|||
|
|
taskId: string;
|
|||
|
|
traceId: string;
|
|||
|
|
businessType: 'TOC' | 'TOB';
|
|||
|
|
}): Promise<{
|
|||
|
|
reportId: string;
|
|||
|
|
testId: string;
|
|||
|
|
timestamp: string;
|
|||
|
|
summary: string;
|
|||
|
|
performanceMetrics: any;
|
|||
|
|
bottlenecks: string[];
|
|||
|
|
recommendations: string[];
|
|||
|
|
}> {
|
|||
|
|
// 生成报告ID
|
|||
|
|
const reportId = `PR-${Date.now()}`;
|
|||
|
|
const timestamp = new Date().toISOString();
|
|||
|
|
|
|||
|
|
// 模拟性能数据
|
|||
|
|
const performanceMetrics = {
|
|||
|
|
system: {
|
|||
|
|
cpuUsage: 65,
|
|||
|
|
memoryUsage: 72,
|
|||
|
|
diskI/O: 45,
|
|||
|
|
networkThroughput: 120
|
|||
|
|
},
|
|||
|
|
application: {
|
|||
|
|
averageResponseTime: 180,
|
|||
|
|
throughput: 850,
|
|||
|
|
errorRate: 0.01,
|
|||
|
|
maxResponseTime: 550,
|
|||
|
|
p95ResponseTime: 320,
|
|||
|
|
p99ResponseTime: 480
|
|||
|
|
},
|
|||
|
|
database: {
|
|||
|
|
queryTime: 80,
|
|||
|
|
connectionPoolUsage: 60,
|
|||
|
|
cacheHitRate: 75
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 生成瓶颈分析
|
|||
|
|
const bottlenecks: string[] = [];
|
|||
|
|
if (performanceMetrics.system.cpuUsage > 70) {
|
|||
|
|
bottlenecks.push('CPU使用率过高');
|
|||
|
|
}
|
|||
|
|
if (performanceMetrics.system.memoryUsage > 80) {
|
|||
|
|
bottlenecks.push('内存使用过高');
|
|||
|
|
}
|
|||
|
|
if (performanceMetrics.application.p95ResponseTime > 300) {
|
|||
|
|
bottlenecks.push('P95响应时间过长');
|
|||
|
|
}
|
|||
|
|
if (performanceMetrics.database.queryTime > 100) {
|
|||
|
|
bottlenecks.push('数据库查询时间过长');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 生成建议
|
|||
|
|
const recommendations: string[] = [];
|
|||
|
|
if (bottlenecks.length > 0) {
|
|||
|
|
recommendations.push('优化系统资源配置');
|
|||
|
|
recommendations.push('考虑数据库索引优化');
|
|||
|
|
recommendations.push('实施缓存策略');
|
|||
|
|
recommendations.push('优化代码逻辑');
|
|||
|
|
} else {
|
|||
|
|
recommendations.push('保持当前系统配置');
|
|||
|
|
recommendations.push('定期进行性能测试');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 生成摘要
|
|||
|
|
const summary = `系统性能良好,平均响应时间 ${performanceMetrics.application.averageResponseTime}ms,吞吐量 ${performanceMetrics.application.throughput} ops/s`;
|
|||
|
|
|
|||
|
|
// 记录报告生成日志
|
|||
|
|
console.log(`[MerchantPerformanceTest] 生成性能报告 - ID: ${reportId}, 测试: ${testId}`, {
|
|||
|
|
...traceInfo,
|
|||
|
|
reportId
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
reportId,
|
|||
|
|
testId,
|
|||
|
|
timestamp,
|
|||
|
|
summary,
|
|||
|
|
performanceMetrics,
|
|||
|
|
bottlenecks,
|
|||
|
|
recommendations
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 执行负载测试
|
|||
|
|
* @param params 测试参数
|
|||
|
|
* @param traceInfo 追踪信息
|
|||
|
|
* @returns 负载测试结果
|
|||
|
|
*/
|
|||
|
|
public static async runLoadTest(params: {
|
|||
|
|
merchantIds: string[];
|
|||
|
|
rampUpTime: number; // ramp-up时间(秒)
|
|||
|
|
steadyStateTime: number; // 稳定状态时间(秒)
|
|||
|
|
operationsPerSecond: number;
|
|||
|
|
}, traceInfo: {
|
|||
|
|
tenantId: string;
|
|||
|
|
shopId: string;
|
|||
|
|
taskId: string;
|
|||
|
|
traceId: string;
|
|||
|
|
businessType: 'TOC' | 'TOB';
|
|||
|
|
}): Promise<{
|
|||
|
|
loadTestId: string;
|
|||
|
|
startTime: string;
|
|||
|
|
endTime: string;
|
|||
|
|
merchantCount: number;
|
|||
|
|
results: Array<{
|
|||
|
|
phase: 'ramp-up' | 'steady-state';
|
|||
|
|
throughput: number;
|
|||
|
|
averageResponseTime: number;
|
|||
|
|
errorRate: number;
|
|||
|
|
}>;
|
|||
|
|
}> {
|
|||
|
|
// 生成负载测试ID
|
|||
|
|
const loadTestId = `LT-${Date.now()}`;
|
|||
|
|
const startTime = new Date().toISOString();
|
|||
|
|
|
|||
|
|
console.log(`[MerchantPerformanceTest] 开始负载测试 - ID: ${loadTestId}, 商户数: ${params.merchantIds.length}`, {
|
|||
|
|
...traceInfo,
|
|||
|
|
loadTestId
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 模拟ramp-up阶段
|
|||
|
|
await new Promise(resolve => setTimeout(resolve, params.rampUpTime * 1000));
|
|||
|
|
|
|||
|
|
// 模拟steady-state阶段
|
|||
|
|
await new Promise(resolve => setTimeout(resolve, params.steadyStateTime * 1000));
|
|||
|
|
|
|||
|
|
// 生成测试结果
|
|||
|
|
const results = [
|
|||
|
|
{
|
|||
|
|
phase: 'ramp-up' as const,
|
|||
|
|
throughput: params.operationsPerSecond * 0.7,
|
|||
|
|
averageResponseTime: 200,
|
|||
|
|
errorRate: 0.005
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
phase: 'steady-state' as const,
|
|||
|
|
throughput: params.operationsPerSecond,
|
|||
|
|
averageResponseTime: 250,
|
|||
|
|
errorRate: 0.01
|
|||
|
|
}
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
const endTime = new Date().toISOString();
|
|||
|
|
|
|||
|
|
// 记录测试完成日志
|
|||
|
|
console.log(`[MerchantPerformanceTest] 负载测试完成 - ID: ${loadTestId}`, {
|
|||
|
|
...traceInfo,
|
|||
|
|
loadTestId
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
loadTestId,
|
|||
|
|
startTime,
|
|||
|
|
endTime,
|
|||
|
|
merchantCount: params.merchantIds.length,
|
|||
|
|
results
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
}
|