preface
In daily development, if a single interface request fails due to interface instability or network jitter, the front-end needs to use a retry policy to solve the problem of system unavailability.
Let’s explore the best retry strategy for the front end.
Basic implementation
For the front-end students with a solid foundation, it is easy to think of the following implementation:
/ * *
* Retry method
* @param {Function} Fn asynchronous function
* @param {number} Times Number of retries
* @param {number} Timeout Indicates the retry waiting time
* @returns
* /
function retry (fn, times, timeout) {
return new Promise((resolve, reject) = > {
const attemp = (a)= > {
fn().then(resolve).catch(err= > {
if (times === 0) {
return reject(err)
}
times--;
setTimeout(attemp, timeout);
});
}
attemp();
});
}
retry(fetchData, 3.1000);
Copy the code
The code is based on the Promise mechanism, which intercepts the reject state of an asynchronous request to retry an asynchronous request.
The overall implementation logic is fine, but a good retry mechanism needs to consider how to set an appropriate retry wait time.
Exponential retreat algorithm
The exponential backoff algorithm is an algorithm to solve how to set the appropriate retry wait time. Its processing flow is as follows:
- The client initiates a network request.
- If the request fails, wait 1 + random_number_milliseconds before retrying the request.
- If the request fails, wait 2 + random_number_milliseconds before retrying the request.
- If the request fails, wait 4 + random_number_milliseconds before retrying the request.
- And so on, the wait time is capped at maximum_backoff.
In the exponential backoff algorithm, the retry waiting time is:
Math.min((2 ** n + random_number_milliseconds), maximum_backoff)
Copy the code
Here random_number_milliseconds is the number of milliseconds (random) less than or equal to 1000. This helps avoid situations where many clients process synchronously and retry simultaneously, causing each wave of requests to be sent synchronously. After each retry, the system recalculates the random_number_milliseconds value.
/ * *
* Generate retry wait time
* @param {number} Times Number of retries
* @param {number} Maximum_backoff Maximum number of seconds to wait
* @returns
* /
function createTimeout(times, maximum_backoff) {
const random_number_milliseconds = Math.floor(Math.random() * 1000);
return Math.min(Math.pow(2, times) * 1000 + random_number_milliseconds, maximum_backoff);
}
Copy the code
According to the algorithm description, the above functions can be implemented to generate the retry wait time.
Next, you can generate a list of retry wait times before making a network request for subsequent retries.
const maximum_backoff = 64 * 1000;
function retry (fn, times) {
const operationTimeout = [];
for (let i = 0; i < times; i++) {
operationTimeout.push(createTimeout(i, maximum_backoff));
}
return new Promise((resolve, reject) = > {
const attemp = (a)= > {
fn().then(resolve).catch(err= > {
if (times === 0) {
return reject(err)
}
times--;
setTimeout(attemp, operationTimeout.shift());
});
}
attemp();
});
}
Copy the code
You can continue to retry after maximum_backoff. However, if the requesting system has been unavailable for a long time, it does not make sense for the client to retry multiple times. Therefore, you can set a deadline and do not retry after maximum_backoff.
const maximum_backoff = 64 * 1000;
function retry (fn, times, deadline) {
const operationTimeout = [];
for (let i = 0; i < times; i++) {
if (deadline < 0) {
break;
}
const timeout = createTimeout(i, maximum_backoff);
deadline -= timeout;
operationTimeout.push(timeout);
}
times = operationTimeout.length;
return new Promise((resolve, reject) = > {
const attemp = (a)= > {
fn().then(resolve).catch(err= > {
if (times === 0) {
return reject(err)
}
times--;
setTimeout(attemp, operationTimeout.shift());
});
}
attemp();
});
}
Copy the code
conclusion
The above is the content of this article, I hope to bring you help, welcome to “attention”, “like”, “forward”.
Reference: https://cloud.google.com/storage/docs/retry-strategy?hl=zh-cn