高频HTTP请求服务器压测实现咨询:Node.js原生http.request方案
针对高并发HTTP负载测试的Node.js优化方案
哥们,你想用Node.js原生http模块实现高并发负载测试的思路是可行的,但你当前的代码存在几个关键问题,会影响并发能力和稳定性,咱们一步步来梳理优化:
你的代码里的潜在问题
- 多定时器竞态问题:你用for循环创建了100个
setInterval,每个间隔设为0,这会让事件循环被大量定时器抢占,而且多个定时器同时判断reqCount,很容易出现多个请求同时发起,导致实际并发量远超你设置的maxConcurrentRequests,瞬间打满资源。 - 错误处理不完整:你只监听了请求的
error事件,但响应对象的错误、请求超时都没处理,会导致失败的请求挂起,占用连接资源。 - 定时器精度问题:
setInterval的实际执行间隔受事件循环影响,高负载下根本达不到“每秒数千次”的精准控制。
优化后的实现方案
咱们换用异步并发池+循环控制的方式,既能精准控制并发数,又能稳定达到高请求量,代码示例如下:
const http = require('http'); // 替换成你的目标服务配置 const config = { hostname: 'your-target-host', port: 80 }; // 最大并发数,根据服务器性能和系统限制调整 const MAX_CONCURRENT = 200; // 测试持续时间,比如1分钟 const TEST_DURATION = 60 * 1000; let activeRequests = 0; let totalRequests = 0; let failedRequests = 0; // 生成唯一不重复的路径 function getRandomUniquePath() { // 用时间戳+随机字符串保证唯一性 return `/load-test/${Date.now()}-${Math.random().toString(36).slice(2, 10)}`; } // 封装单个请求的Promise function sendSingleRequest() { return new Promise((resolve, reject) => { activeRequests++; totalRequests++; const req = http.request({ hostname: config.hostname, port: config.port, path: getRandomUniquePath(), method: 'GET', agent: false, // 禁用连接池,每个请求新建TCP连接 timeout: 5000 // 设置5秒超时,避免请求挂起 }, (res) => { // 必须消费响应数据,否则会内存泄漏 res.resume(); res.on('end', () => { activeRequests--; resolve(); }); }); // 处理请求错误 req.on('error', (err) => { failedRequests++; activeRequests--; reject(err); }); // 处理超时 req.on('timeout', () => { failedRequests++; activeRequests--; req.destroy(); reject(new Error('Request timed out')); }); req.end(); }); } // 主测试逻辑 async function runLoadTest() { const testEndTime = Date.now() + TEST_DURATION; // 循环发送请求直到测试结束 while (Date.now() < testEndTime) { // 控制并发数,不超过最大值 if (activeRequests < MAX_CONCURRENT) { sendSingleRequest().catch(err => { console.error(`请求失败: ${err.message}`); }); // 调整这个间隔可以控制请求速率,比如设为1ms就是每秒约1000次 await new Promise(resolve => setTimeout(resolve, 1)); } else { // 并发满了就等待1ms再检查 await new Promise(resolve => setTimeout(resolve, 1)); } } // 等待所有活跃请求完成后输出统计 while (activeRequests > 0) { await new Promise(resolve => setTimeout(resolve, 100)); } console.log('\n===== 负载测试结果 ====='); console.log(`总请求数: ${totalRequests}`); console.log(`失败请求数: ${failedRequests}`); console.log(`成功率: ${(((totalRequests - failedRequests)/totalRequests)*100).toFixed(2)}%`); } // 启动测试 runLoadTest();
额外的优化建议
- 调整系统资源限制:高并发下Node.js会打开大量TCP连接,Linux系统默认的文件描述符限制(一般是1024)不够用,需要临时调整
ulimit -n 65535,或者修改/etc/security/limits.conf永久设置。 - 考虑专用负载测试工具:如果你的需求是专业级测试,推荐用Artillery、k6这类工具,它们已经封装了并发控制、统计分析、报告生成等功能,比自己写代码高效得多。但如果必须用Node.js原生实现,上面的方案足够稳定。
- 监控资源使用:测试时可以用
process.memoryUsage()和os.cpus()监控内存和CPU负载,避免进程因资源耗尽崩溃。
内容的提问来源于stack exchange,提问作者Forivin
相关产品推荐
相关产品推荐

