低成本高收益:用LocalStorage构建接口流量闸门

通过有效期控制与缓存一致性校验,将非频繁更新接口的调用量降低70%

背景

在前端开发中,接口的调用频率往往随着用户体量的增长而成倍提升。我们某个产品使用了“券商配置”接口(作用:根据不同的客户,返回对应的线上脚本地址,动态加载),最初服务的客户体量较小,接口被频繁调用但未造成明显压力。然而,随着某大型券商的接入,接口访问量激增,后端压力骤增,甚至影响了整体服务的稳定性。

问题暴露

  • 前端层面:高频接口在页面生命周期内被多次重复请求,造成了大量冗余流量。
  • 后端层面:接口服务压力大,响应变慢,影响用户体验。
  • 运维层面:传统的服务端限流、缓存、扩容方案部署成本高、见效慢。
  • 代码层面:由于历史架构原因,不能直接改动接口调用的逻辑,只能考虑通过注入增量脚本代码的形式处理此问题。

解决思路

  • 接口请求底层实现方式为xhr,所以使用xhr原型方法拦截指定接口,处理缓存逻辑。

  • 前端localstorage本地缓存,优先在浏览器端缓存接口数据,缓存失效时再重新请求接口。这样可以极大减少接口请求次数,降低网关接口压力。

技术实现

1. 带有效期的 localStorage 封装

  • 支持设置缓存有效期,自动失效清理。

/**
 * 本地缓存工具,支持设置有效期。
 * set: 存储数据并设置过期时间。
 * get: 读取数据,自动判断是否过期。
 * remove: 删除指定 key 的缓存。
 */
const myLocalStorage = {
  /** 存储数据到 localStorage,并设置有效期 */
  set: function (key, value, expires) {
    var data = {
      value, // 实际存储内容
      expires: new Date().getTime() + expires * 1000 // 过期时间戳
    };
    localStorage.setItem(key, JSON.stringify(data));
  },
  /** 读取缓存,自动判断是否过期,过期则清除 */
  get: function (key) {
    var data = JSON.parse(localStorage.getItem(key));
    if (data !== null) {
      // 判断是否过期
      if (data.expires !== null && data.expires < new Date().getTime()) {
        localStorage.removeItem(key); // 过期自动清除
      } else {
        return data.value; // 未过期返回内容
      }
    }
    return null;
  },
  /** 删除指定 key 的缓存 */
  remove: function (key) {
    localStorage.removeItem(key);
  }
};

2. 接口缓存逻辑

  • 先查缓存,有则直接用,无则请求接口并写入缓存。
  • 缓存有效期可灵活配置(如40分钟)。

/**
 * 券商配置接口缓存处理主逻辑。
 * 1. 先查 localStorage 是否有有效缓存。
 * 2. 有缓存则直接用,无缓存则发起接口请求并写入缓存。
 * 3. 缓存有效期可灵活配置(如 40 分钟)。
 * @param {string} oldUrl - 原始接口地址
 */
const brokerCountdown = 40 * 60; // 设置接口缓存有效期40分钟
function handleBrokerConfig(url) {
  const brokerConfigData = myLocalStorage.get('brokerConfigData'); // 读取缓存
  if (!brokerConfigData) { // 缓存不存在,发起请求
    fetch(url, {
      method: 'GET'
    })
      .then(res => res.json())
      .then(data => {
        if (data && data.data) {
          setBrokerConfig(data.data); // 设置页面券商配置
          // 写入缓存,40分钟有效
          myLocalStorage.set('brokerConfigData', JSON.stringify(data.data), brokerCountdown); 
        }
      });
  } else { 
    // 缓存存在,直接用
    const data = JSON.parse(brokerConfigData);
    setBrokerConfig(data); // 设置页面券商配置
  }
}
/** 设置券商配置:挂载对应券商的js、css生产地址 */
function setBrokerConfig(data){
  const { js_url, css_url } = data;
  // 挂载js脚本...
  // 挂载css样式文件...
}

3. 拦截 XHR,自动接管接口请求

  • 对原有业务代码无侵入,兼容性好。

/**
 * 拦截所有 XHR 请求,自动接管券商配置接口。
 * 只对 broker/config 接口生效,其他请求不受影响。
 */
var origOpen = xhrProto.open;
xhrProto.open = function () {
  if (arguments[1].indexOf('broker/config') > -1) {
    var params = arguments[1];
    handleBrokerConfig(params); // 走本地缓存逻辑
    return;
  }
  return origOpen.apply(this, arguments); // 其他请求正常发送
};

实施效果

  • 流量降低:接口流量下降约70%,后端压力大幅缓解。
  • 用户体验提升:页面加载更快,数据响应更及时。
  • 低成本高收益:仅需前端少量代码改造,无需后端配合,见效极快。

本地缓存是前端降本增效的利器,尤其适用于高频调用、数据变化不频繁的接口。通过简单的 localStorage 封装和 XHR 拦截,我们用极低的开发成本,解决了大客户带来的高并发流量问题,这一方案值得在更多类似场景中推广应用。

posted @ 2025-06-11 16:21  Justus-  阅读(47)  评论(0)    收藏  举报