文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

我们一起聊聊前端接口容灾

2024-11-30 04:59

关注

还能咋样,白屏呗。

有没有不白屏的方案?

有啊,还挺简单的。

容我细细细细分析。

原因就是接口挂了,拿不到数据了。那把数据储存起来就可以解决问题。

思考

存哪里?

第一时间反应浏览器本地存储,想起了四兄弟。

选型对比

特性

cookie

localStorage

sessionStorage

indexDB

数据生命周期

服务器或者客户端都可以设置、有过期时间

一直存在

关闭页面就清空

一直存在

数据储存大小

4KB

5MB

5MB

动态,很大

大于250MB

与服务器通信

每次都带在header中

不带

不带

不带

兼容性

都支持

都支持

都支持

IE不支持,其他主流都支持

考虑到需要存储的数据量,5MB 一定不够的,所以选择了 IndexDB。

考虑新用户或者长时间未访问老用户,会取不到缓存数据与陈旧的数据。

因此准备上云,用阿里云存储,用 CDN 来保障。

总结下:线上 CDN、线下 IndexDB。

整体方案

整体流程图

图片

CDN

先讲讲线上 CDN。

通常情况下可以让后端支撑,本质就是更新策略问题,这里不细说。

我们讲讲另外一种方案,单独启个 Node 服务更新 CDN 数据。

流程图

图片

劫持逻辑

劫持所有接口,判断接口状态与缓存标识。从而进行更新数据、获取数据、缓存策略三种操作

通过配置白名单来控制接口存与取

axios.interceptors.response.use(
      async (resp) => {
        const { config } = resp
        const { url } = config
        // 是否有缓存tag,用于更新CDN数据。目前是定时服务在跑,访问页面带上tag
        if (this.hasCdnTag() && this.isWhiteApi(url)) {
          this.updateCDN(config, resp)
        }
        return resp;
      },
      async (err) => {
        const { config } = err
        const { url } = config
        // 是否命中缓存策略
        if (this.isWhiteApi(url) && this.useCache()) {
          return this.fetchCDN(config).then(res => {
            pushLog(`cdn缓存数据已命中,请处理`, SentryTypeEnum.error)
            return res
          }).catch(()=>{
           pushLog(`cdn缓存数据未同步,请处理`, SentryTypeEnum.error)
          })
        }
      }
    );

缓存策略

累计接口异常发生 maxCount 次,打开缓存开关,expiresSeconds 秒后关闭。

缓存开关用避免网络波动导致命中缓存,设置了阀值。


useCache = () => {
  if (this.expiresStamp > +new Date()) {
    const d = new Date(this.expiresStamp)
    console.warn(`
    ---------------------------------------
    ---------------------------------------
    启用缓存中
    关闭时间:${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}
    ---------------------------------------
    ---------------------------------------
    `)
    return true
  }
  this.errorCount += 1
  localStorage.setItem(CACHE_ERROR_COUNT_KEY, `${this.errorCount}`)
  if (this.errorCount > this.maxCount) {
    this.expiresStamp = +new Date() + this.expiresSeconds * 1000
    this.errorCount = 0
    localStorage.setItem(CACHE_EXPIRES_KEY, `${this.expiresStamp}`)
    localStorage.removeItem(CACHE_ERROR_COUNT_KEY)
    return true
  }
  return false
}

唯一标识

根据 method、url、data 三者来标识接口,保证接口的唯一性

带动态标识,譬如时间戳等可以手动过滤


generateCacheKey = (config) => {
  // 请求方式,参数,请求地址,
  const { method, url, data, params } = config;
  let rawData = ''
  if (method === 'get') {
    rawData = params
  }
  if (method === 'post') {
    rawData = JSON.parse(data)
  }
  // 返回拼接key
  return `${encodeURIComponent([method, url, stringify(rawData)].join('_'))}.json`;
};

更新数据


updateCDN = (config, data) => {
  const fileName = this.generateCacheKey(config)
  const cdnUrl = `${this.prefix}/${fileName}`
  axios.post(`${this.nodeDomain}/cdn/update`, {
    cdnUrl,
    data
  })
}

Node定时任务

构建定时任务,用 puppeteer 去访问、带上缓存标识,去更新 CDN 数据

import schedule from 'node-schedule';

const scheduleJob = {};

export const xxxJob = (ctx) => {
  const { xxx } = ctx.config;
  ctx.logger.info(xxx, 'xxx');
  const { key, url, rule } = xxx;
  if (scheduleJob[key]) {
    scheduleJob[key].cancel();
  }
  scheduleJob[key] = schedule.scheduleJob(rule, async () => {
    ctx.logger.info(url, new Date());
    await browserIndex(ctx, url);
  });
};

export const browserIndex = async (ctx, domain) => {
  ctx.logger.info('browser --start', domain);
  if (!domain) {
    ctx.logger.error('domain为空');
    return false;
  }
  const browser = await puppeteer.launch({
    args: [
      '--use-gl=egl',
      '--disable-gpu',
      '--no-sandbox',
      '--disable-setuid-sandbox',
    ],
    executablePath: process.env.CHROMIUM_PATH,
    headless: true,
    timeout: 0,
  });
  const page = await browser.newPage();
  await page.goto(`${domain}?${URL_CACHE_KEY}`);
  await sleep(10000);
  // 访问首页所有查询接口
  const list = await page.$$('.po-tabs__item');
  if (list?.length) {
    for (let i = 0; i < list.length; i++) {
      await list[i].click();
    }
  }
  await browser.close();
  ctx.logger.info('browser --finish', domain);
  return true;
};

效果

手动 block 整个 domain,整个页面正常展示

图片

IndexDB

线上有 CDN 保证了,线下就轮到 IndexDB 了,基于业务简单的增删改查,选用 localForage 三方库足矣。

axios.interceptors.response.use(
      async (resp) => {
        const { config } = resp
        const { url } = config
        // 是否有缓存tag,用于更新CDN数据。目前是定时服务在跑,访问页面带上tag
        if (this.hasCdnTag() && this.isWhiteApi(url)) {
          this.updateCDN(config, resp)
        }
        if(this.isIndexDBWhiteApi(url)){
          this.updateIndexDB(config, resp)
        }
        return resp;
      },
      async (err) => {
        const { config } = err
        const { url } = config
        // 是否命中缓存策略
        if (this.isWhiteApi(url) && this.useCache()) {
          return this.fetchCDN(config).then(res => {
            pushLog(`cdn缓存数据已命中,请处理`, SentryTypeEnum.error)
            return res
          }).catch(()=>{
           pushLog(`cdn缓存数据未同步,请处理`, SentryTypeEnum.error)
           if(this.isIndexDBWhiteApi(url)){
             return this.fetchIndexDB(config).then(res => {
              pushLog(`IndexDB缓存数据已命中,请处理`, SentryTypeEnum.error)
              return res
            }).catch(()=>{
             pushLog(`IndexDB缓存数据未同步,请处理`, SentryTypeEnum.error)
            })
           }
          })
        }
      }
    );

总结

总结下,优点包括不入侵业务代码,不影响现有业务,随上随用,尽可能避免前端纯白屏的场景,成本低。劣势包括使用局限,不适合对数据实效性比较高的业务场景,不支持 IE 浏览器。

接口容灾我们也是刚弄不久,有许多细节与不足,欢迎沟通交流。

接口容灾本意是预防发生接口服务挂了的场景,我们不会很被动。原来是P0的故障,能被它降低为 P2、P3,甚至在某些场景下都不会有用户反馈。

来源:政采云技术内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯