首页 > 编程语言 >重试,让程序更健壮

重试,让程序更健壮

时间:2023-04-11 14:46:36浏览次数:43  
标签:健壮 const 请求 发起 程序 重试 error retryCount

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

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

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

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

标准 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 one rror(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);

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

欢迎批评指正。

作者:袁首京

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

标签:健壮,const,请求,发起,程序,重试,error,retryCount
From: https://www.cnblogs.com/rockety/p/17306156.html

相关文章

  • winform程序在不同操作系统下的兼容问题
    建议用.netframework3.5作为生成目标,CPU设置为any来开发,然后在app.config文件里加上<?xmlversion="1.0"encoding="utf-8"?><configuration><startupuseLegacyV2RuntimeActivationPolicy="true"><supportedRuntimeversi......
  • 如何在移动应用开发中,用小程序实践灰度发布策略
    在当今移动应用市场竞争激烈的环境下,如何更快地发布新版本、更精确地测试和调整、更好地了解用户需求和行为,成为了每个App开发者面临的重要挑战。在这个背景下,灰度发布和小程序容器技术成为了越来越受欢迎的解决方案。 灰度发布是指将新版本应用程序推送给一部分用户进行测......
  • Python程序笔记20230303
    成绩评级程序分数<60,D60<=分数<80,C80<=分数<90,B90<=分数<100,A分数==100,S#输入分数score=int(input("请输入分数:"))#判断评级ifscore<0orscore>100:print("无效的分数")elifscore<60:print("......
  • AI 绘画 API 超详细使用教程 - 附微信小程序接入代码
    写在前面【AI绘画/AI图像生成】已成为现下炙手可热的话题,AI大模型训练的成本高昂,算法研究时间周期较长,对于大多数人来说,自研一套算法模型还是非常困难的,因此AI绘画API就应运而生,直接调用AI绘画API就能轻松将先进的图文AI融入到我们的产品中,使用门槛是非常低的。 本......
  • Python程序笔记20230302
    Alice、Bob和他们的朋友们问题主体密码学家Rivest、Shamir、Adleman于1977年4月撰写了一篇论文《数字签名与公钥密码学》(OnDigitalSignaturesandPublic-KeyCryptosystems),并投稿至了一个期刊上,不过很遗憾这篇论文被拒稿了。随后他们修改了论文,并将论文重新命名为《一种实......
  • Python程序笔记20230301
    打印九九乘法表foriinrange(1,10):forjinrange(1,i+1):print(i,"x",j,"=",i*j,end='')print("\n")第三行的print(i,"x",j,"=",i*j,end='')打印出i和j的乘积,并在末尾添......
  • uniapp小程序使用高德地图api实现路线规划
    uniapp小程序使用高德地图api实现路线规划 Postedon 2023-01-1011:18  书中枫叶 阅读(1387) 评论(3)  编辑  收藏  举报路线规划简介路线规划常用于出行路线的提前预览,我们提供4种类型的路线规划,分别为:驾车、步行、公交和骑行,满足各种的出行场景。高德开放......
  • 单片机程序运行过程中,某些变量被莫名其妙的修改了
     在开发单片机程序中,遇到这么一个问题,程序运行过程中,某些变量被莫名其妙的修改了,然而经过打断点还有打印信息都完全查不出哪里出了问题,直到我灵光一闪。解决方法:查map文件,定位到被修改的变量,然后往上查看有可能的数组。后面经查看找到了可疑数组。然后再查看相关代码。发......
  • 面向对象 程序分析 友元函数
    什么是友元函数?友元函数(friendfunction)是C++中一个特殊的函数类型。它不是类的成员函数,但它可以访问类的私有(private)和保护(protected)成员。友元函数提供了一种突破类封装的机制,允许在类之外的代码访问类的私有和保护成员。当你想要让某个函数访问一个类的私有和保护成员时,可以......
  • 小程序自定义省市二级联动
    conststr=[{id:"110000",name:"北京市",city:[{id:"110100",name:"北京市",area:[{id:"110101",name:"东城区"},{id:"110102",name:"西城区"},{id:"110105",name:"朝阳区"},{id:"......