面试题答案
一键面试重试机制策略设计
-
重试次数: 可以根据实际情况设定一个合理的重试次数,比如3次。如果多次重试都失败,可能说明问题较为严重,不适合继续重试。
-
重试间隔时间计算方式:
- 固定间隔:每次重试间隔固定时间,例如每次间隔1秒。这种方式简单直接,但在面对一些瞬时网络问题时可能不够灵活。
- 指数退避:每次重试间隔时间呈指数增长,例如初始间隔为1秒,下次间隔为2秒,再下次为4秒等。这种方式可以避免短时间内频繁重试对服务器造成过大压力,尤其适用于服务器过载导致请求失败的情况。
-
与超时机制协同工作:
- 为每个请求设置一个总的超时时间,比如5秒。在重试过程中,如果累计重试时间加上当前请求时间超过总超时时间,则停止重试并返回失败。
代码示例(使用指数退避和超时机制)
const axios = require('axios');
async function makeRequestWithRetry(url, maxRetries = 3, baseRetryTime = 1000, totalTimeout = 5000) {
let retries = 0;
let elapsedTime = 0;
while (retries < maxRetries) {
try {
const response = await Promise.race([
axios.get(url),
new Promise((_, reject) => {
setTimeout(() => {
reject(new Error('Request timed out'));
}, totalTimeout - elapsedTime);
})
]);
return response;
} catch (error) {
if (error.message.includes('Request timed out')) {
throw error;
}
const retryTime = baseRetryTime * Math.pow(2, retries);
elapsedTime += retryTime;
if (elapsedTime > totalTimeout) {
throw new Error('Total time for retries exceeded');
}
console.log(`Retry ${retries + 1} in ${retryTime / 1000} seconds...`);
await new Promise(resolve => setTimeout(resolve, retryTime));
retries++;
}
}
throw new Error('Max retries reached, request failed');
}
// 使用示例
makeRequestWithRetry('https://unstable-api.example.com/api/data')
.then(response => {
console.log('Success:', response.data);
})
.catch(error => {
console.error('Error:', error.message);
});
在上述代码中:
makeRequestWithRetry
函数接受URL、最大重试次数maxRetries
、基础重试时间baseRetryTime
(单位毫秒)和总超时时间totalTimeout
(单位毫秒)作为参数。- 使用
Promise.race
来实现请求和超时的竞争,确保请求不会超过总超时时间。 - 在每次请求失败时,计算下一次重试的间隔时间(指数退避),并累计已花费的时间。如果累计时间超过总超时时间,则停止重试并抛出错误。
- 如果重试次数达到
maxRetries
仍未成功,也抛出错误。