记一次奇葩接口 ~ 失败重试12小时

1.回传接口要求

第一次遇到这么奇葩的API接口回传要求:

  1. HTTP Status为500、1000、或者超时、响应慢都要重试
  2. 前10分钟每30s重试一次。后续每5分钟重试一次。如果12小时还未成功直接丢弃数据

你说数据重要嘛,你后面又不要了,说不重要嘛12h的重试。。。所以避免折腾,所有丢弃的数据还是得本地记录下日志

2.思路历程

一开始是用定时任务来处理,后来说太麻烦,让前端解决。。。

得写个计时器完事。后来又说逻辑太复杂,要简单便于维护。。。

那好,直接使用axiosRetry,咱们也不搞啥算法了,就给它指定一个自定义的retryDelay函数

也不要那么多复杂逻辑了,直接给您算好大概重试多少次,比如说:

// 添加axios-retry插件,配置重试策略
axiosRetry(jdRetryAxios, {
    retries: 100, // 重试次数:差不多得了,它让你24h你还真24h重试不成?  
    retryDelay: (retryCount) => {
        console.debug('retryCount:', retryCount);
        if (retryCount <= 19) { // 前10分钟,每30s重试一次 ==> 20次
            return 30000; // 30 * 1000;
        } else { // 后续重试时间间隔每次间隔5分钟,最长12小时 ==> 144次
            return 300000; //5 * 60 * 1000;
        }
    },
    shouldResetTimeout: true, // 每次重试都重置超时时间
    // 自定义条件,针对状态为500、1000、超时、网络问题进行重试
    retryCondition: (error) => {
        console.debug('retry touch:', error);
        return error?.response?.status === 500 || // JD服务器内部错误
            error?.response?.status === 1000 || // JD服务器内部错误
            error?.code === 'ECONNABORTED' || // 后端响应超时
            error?.code == 'ERR_NETWORK'; // 网络异常
    },
});

3.潜在风险

但这种其实有2个潜在的问题:

1.有些请求其实只是响应超时,并不代表服务器没有响应

PS:等它来得及的时候就会一下把你之前的重试都响应给你了,你得鉴别,eg:token、timestamp

2.客户端可能会多次post请求,那你就要想办法去重

PS:这种反馈统计的一般都不会让你点,往往是程序自己后台默默去做的事情那事件就别暴露的那么明显了。就算是让点的,那你至少把个按钮变为禁用状态(可以多少时间后恢复)

解决多次请求的问题其实可以通过前后端来共同处理:(主要还是后端处理,前端是尽量避免和延缓)

  1. 比如UI层面的禁用和多长时间恢复
  2. 比如每个请求都可以带上一个时间戳,后端只要看到时间戳超过5s/10s的直接拒掉了(超时拒绝响应
    1. PS:这个最简单,尤其是对于服务器配置不高的情况。除了这种方法,还可以通过限流算法来处理
  3. 再比如前端在请求前搞个类似hash或者队列的数据结构,同一个连接别陆续请求多次,后端类似于ResponseCache的东西,让浏览器对相同请求进行缓存下
  4. 再比如后端通过各种缓存(eg:redis)、令牌桶之类的限流算法来处理

不扯了,先这样

posted @ 2023-08-17 14:44  鲲逸鹏  阅读(14)  评论(0编辑  收藏  举报