MST

星途 面试题库

面试题:Node.js高并发HTTP请求错误捕获与响应策略

假设你的Node.js应用需要同时发起大量的HTTP请求(例如1000个),在这种高并发场景下,如何高效地捕获每个请求的错误,并确保即使部分请求失败,整体应用仍能正常运行且尽可能快速地响应。阐述详细的设计方案,并说明如何优化资源利用和错误处理的性能。
24.4万 热度难度
前端开发Node.js

知识考点

AI 面试

面试题答案

一键面试
  1. 设计方案
    • 使用Promise.allSettled
      • Promise.allSettled方法接受一个Promise数组作为参数,它会返回一个新的Promise。这个新的Promise在所有输入的Promise都已经被解决(无论是成功还是失败)时才会被解决。
      • 示例代码如下:
const axios = require('axios');

const requests = Array.from({ length: 1000 }, (_, i) =>
  axios.get(`https://example.com/api/${i}`)
);

Promise.allSettled(requests)
 .then(results => {
      results.forEach((result, index) => {
          if (result.status === 'fulfilled') {
              console.log(`Request ${index} success:`, result.value);
          } else {
              console.log(`Request ${index} failed:`, result.reason);
          }
      });
      // 在这里可以进行整体应用的后续逻辑,即使部分请求失败也不影响
  });
  • 控制并发数量
    • 使用队列来管理请求,通过设置一个并发限制,确保同时进行的请求数量在合理范围内,避免资源耗尽。例如,可以使用async - await结合Promise来实现。
    • 示例代码如下:
const axios = require('axios');

async function sendRequestsWithLimit(requests, limit) {
    const results = [];
    const queue = requests.slice();
    const running = [];

    async function processQueue() {
        while (queue.length > 0 && running.length < limit) {
            const request = queue.shift();
            const promise = request();
            running.push(promise);
            try {
                const result = await promise;
                results.push({ status: 'fulfilled', value: result });
            } catch (error) {
                results.push({ status:'rejected', reason: error });
            }
            running.splice(running.indexOf(promise), 1);
            processQueue();
        }
    }

    processQueue();

    while (running.length > 0) {
        await Promise.race(running);
    }

    return results;
}

const requests = Array.from({ length: 1000 }, (_, i) => () =>
    axios.get(`https://example.com/api/${i}`)
);

sendRequestsWithLimit(requests, 100)
   .then(results => {
        results.forEach((result, index) => {
            if (result.status === 'fulfilled') {
                console.log(`Request ${index} success:`, result.value);
            } else {
                console.log(`Request ${index} failed:`, result.reason);
            }
        });
    });
  1. 优化资源利用和错误处理性能
    • 优化资源利用
      • 设置合理的并发限制:根据服务器的性能和网络状况,调整并发请求的数量。例如,如果服务器的CPU和内存资源有限,减少并发数可以避免系统资源耗尽。通过测试不同的并发限制值,找到一个既能充分利用资源又不影响性能的平衡点。
      • 复用HTTP连接:使用http.Agent(在axios中默认会复用连接)来复用TCP连接,减少建立新连接的开销。例如,在axios中可以通过设置axios.defaults.agent来定制连接池的行为。
    • 优化错误处理性能
      • 快速失败策略:对于一些明显会失败的请求(例如请求的URL格式错误),在请求发起前进行检查并直接标记为失败,避免不必要的网络请求。
      • 错误日志处理:将错误信息进行分类和统计,只记录关键的错误信息,避免大量无用的日志输出影响性能。可以使用专门的日志库(如winston)来管理日志记录,设置不同的日志级别(如errorinfo等)。