重试,让程序更健壮

任何通过网络与其它应用通讯地的程序,都应该有足够的灵活性,来应对短暂的临时性故障。因为这些故障很多时候是可以自恢复的。

例如,为了避免服务过载,很多应用会采取某些限流措施,在并发请求达到一定数量时,暂时性的拒绝新的请求加入。这种情况下,尝试使用该应用的程序,一开始可能会被拒绝连接,但下一刻就好了。

因此,在设计系统时,应该考虑到此种故障。并且在条件允许时,加入重试机制,自动再次发起相应的请求。在某些情况下,可能会显著的改善应用程序的用户体验。

重试,让程序更健壮

能否发起重试,最重要的前提之一是,对同一资源的发起多次相同的请求,能否得到相同的结果。即资源接口是否具有幂等性。

标准 REST API 中,GET/HEAD/OPTIONS 通常是不会更改服务器上的资源的,因此大多是可重试的。

换个说法就是,如果能够确定,下次请求有可能成功,那就可以尝试重试。否则的话,就不必浪费时间、精力以及系统资源了。

例如,在请求 HTTP 服务时,收到 503 或 408 这样的状态码,则重试可能会有效;但是如果收到了 401 或 403 之类的状态码,则简单的重试肯定不起作用。

确定了什么情况下发起重试后,还有另外一个问题值得考虑。即在什么时间、以什么样的频率发起重试。尽管可以,但通常并不会是请求失败后,立即发起重试,而是需要根据具体的场景,选择合适的重试
时机。

假如说我们请求失败的原因,是服务端请求过载。则立即发起重试,除了给服务端添乱外,不会有其它结果。严重情况下,可能会加剧服务器的负担,直到耗尽服务器资源。

为了避免上述问题,常见的做法是在重试之前增加一些延迟。但是如何增加这些延迟,又有多种策略,比较多使用的有两种:

  • 固定间隔。即每次请求失败后,都等待固定的时间后,再次发起下次重试请求;
  • 指数递增。即多次请求之间的延时,成倍增加;

如果失败是由服务端过载引起的,则后一种策略可能会更好。假如它的初始请求在 0ms 发出,则第二次请求在失败 200ms 后发出,第三次请求在失败 400ms 后发出,第四次在 800ms... 以此类推。这种分散的请求和重试机制,可能有助于减缓客户端及服务器的负载,提高我们最终获取到成功结果的机会。

但是假如所有的请求都从同一时刻发起,并按照同样的机制延时重试,则两种策略是一样的,并不会有所改进。这种情况下,可能需要加入一些随机因素。

扯的有点多,接下来搞些实际的,上一点儿代码。简单起见,这里演示一下在 JavaScript 中的实现,使用诸位都了解的 axios。Axios 提供了拦截器机制,用来处理通用的重试逻辑正合适。

const SLEEP_TIME = 200;
const RETRY_TIMES = 3;
const RETRY_STATUS = [408, 503, 504];

function getSleepTime(i = 0) {
  const wTime = Math.min(SLEEP_TIME * 2 ** i);
  return Math.random() * wTime;
}

async function fakeSleep(ms) {
  await new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, ms);
  });
}

async function onError(error) {
  const { status } = error.response;
  let { retryCount = 0 } = error.response.config;

  if (RETRY_STATUS.includes(status) && retryCount < RETRY_TIMES) {
    retryCount += 1;
    sleep_ms = getSleepTime(retryCount);
    await fakeSleep(sleep_ms);

    error.config.retryCount = retryCount;
    return await axios(error.config);
  }
}

axios.interceptors.response.use(onError);

代码不多,应该不需要额外的解释。其它编程语言,实现思路大致也差不多。相信您肯定可以写出更好的。

欢迎批评指正。

作者:袁首京

原创文章,转载时请保留此声明,并给出原文连接。

原文链接:https://www.cnblogs.com/rockety/p/17306156.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:重试,让程序更健壮 - Python技术站

(0)
上一篇 2023年4月17日
下一篇 2023年4月17日

相关文章

  • JavaScript相等运算符的九条规则示例详解

    当我们在编写JavaScript代码时,常常需要判断两个变量是否相等,这时候就需要使用相等运算符,即==和===。但是,由于JavaScript的这两种相等运算符在使用时存在很多陷阱和特殊情况,所以需要我们特别注意。以下是详细的JavaScript相等运算符的九条规则和示例详解。 规则一:如果两个变量类型不同,则不相等 例如,以下代码的输出结果为false:…

    JavaScript 2023年5月28日
    00
  • JavaScript迭代器的含义及用法

    JavaScript迭代器的含义及用法 在Javascript中,迭代器指的是一个能够依次访问集合中的元素的对象。 同时,该示例还实现了一个迭代器方法,可以用来访问集合的每一个元素。 迭代器是用于解决循环一个集合并访问其每个元素的问题。 迭代器对象就像计算机科学中所说的迭代器一样,它跟踪集合中的元素并在必要时返回下一个元素。 迭代器方法返回的对象具有一个ne…

    JavaScript 2023年5月18日
    00
  • js四舍五入数学函数round使用实例

    关于 JavaScript 中四舍五入数学函数 round() 的使用实例,这里提供一份完整攻略: round() 函数简介 round() 函数是 JavaScript 内置的一个数学函数,用于四舍五入取整。该函数可以接收一个数值类型的参数,并返回一个整数。 语法结构如下: Math.round(x) 其中,参数 x 是需要进行四舍五入取整的数值。 使用实…

    JavaScript 2023年5月27日
    00
  • 详谈js遍历集合(Array,Map,Set)

    我来为你讲解如何用JavaScript遍历集合。 集合的遍历 在遍历集合之前,首先需要了解集合类型的基本特性。 JavaScript中常见的集合类型有Array、Map和Set。其中: Array是一种有序、可重复的数据集合,它可以通过下标或迭代器来访问其中的元素。 Map是一种关联数组,它保存了键值对,并且键可以是任意类型的数据,而值可以是任意类型的数据。…

    JavaScript 2023年5月27日
    00
  • JS 俄罗斯方块完美注释版代码

    JS 俄罗斯方块完美注释版代码是一款非常经典的俄罗斯方块游戏,在学习 JavaScript 编程的过程中非常适合进行体验和学习。下面,我将给出关于这款游戏的完整攻略,帮助初学者更好地理解代码和游戏逻辑。 准备工作 在开始阅读代码之前,我们需要先完成以下准备工作: 安装浏览器:在电脑上安装 Google Chrome、Firefox 等主流浏览器。 下载源代码…

    JavaScript 2023年5月28日
    00
  • javascript比较两个日期相差天数的方法

    对于JavaScript来说,比较两个日期相差天数的方法可以使用以下两种方式: 方式一:使用Date对象获取时间戳进行计算 我们可以将两个日期转化为时间戳,然后计算它们之间相差的毫秒数,最后再将毫秒数换算成天数。 /** * 计算两个日期相差的天数 * @param {string} date1 日期1,格式为 yyyy-mm-dd * @param {st…

    JavaScript 2023年5月28日
    00
  • event.X和event.clientX的区别分析

    那么让我们来详细分析一下“event.X和event.clientX的区别”。 1. 事件对象(event)简介 在JavaScript中,与事件相关的数据都被封装在一个事件对象中,该对象用来携带事件发生时的一些信息,比如事件类型、目标元素、鼠标坐标、键盘按键等。 2. event.X和event.clientX的区别 event.X表示鼠标相对于当前元素的…

    JavaScript 2023年6月11日
    00
  • JavaScript使用cookie实现记住账号密码功能

    一、什么是cookie? 在介绍如何使用cookie实现记住账号密码功能前,我们先来了解一下什么是cookie。 Cookie是一种存储在用户计算机上的小文件。当用户访问网站时,网站会在用户计算机上存储一些数据,并在以后访问该网站时使用这些数据。Cookie主要用于跟踪用户,在用户浏览网站时保持用户状态以及在一段时间内记录用户在网站上的活动。 二、使用coo…

    JavaScript 2023年6月11日
    00
合作推广
合作推广
分享本页
返回顶部