IIWAB 高并发场景下前端按钮状态控制 - IIWAB

高并发场景下前端按钮状态控制

IIWAB 1月前 ⋅ 57 阅读

通过一个超轻量化的 status.js 文件(仅控制时间逻辑),在活动开始前禁用按钮(置灰),活动开始时更新这个 JS 文件,利用 CDN 短缓存(1秒)的特性,让全网用户瞬间同步生效,无需刷新页面即可解锁按钮。

一、核心实现思路

这个方案的关键是极简的 JS 文件 + CDN 短缓存 + 前端轮询/即时加载,既保证千万级访问下的性能,又能做到秒级生效:

  1. status.js 仅暴露一个全局变量(如活动开始时间/状态),文件体积控制在几十字节内;
  2. CDN 配置该文件缓存时间为 1 秒,保证更新后全网快速同步;
  3. 前端页面加载时立即请求该文件,通过判断全局变量控制按钮状态,可选轮询确保活动开始瞬间生效。

二、完整实现方案

1. 第一步:编写极简的 status.js 文件(核心控制文件)

这个文件是整个方案的核心,仅需一行代码,体积不到 50 字节,示例如下:

// 活动未开始状态(上线初期部署这个版本)
window.activityStatus = {startTime: 1740000000000, isActive: false};

// 活动开始后更新为这个版本(替换上面一行即可)
// window.activityStatus = {startTime: 1740000000000, isActive: true};
  • startTime:活动开始的时间戳(毫秒)(如 1740000000000 对应具体时间);
  • isActive:活动是否已开始(布尔值,核心控制字段);
  • 注意:文件编码为 UTF-8,去除所有多余空格/注释,确保体积最小。

2. 第二步:CDN 配置(关键!确保1秒缓存+回源策略)

status.js 配置以下 CDN 规则(以阿里云CDN/腾讯云CDN为例):

# 核心配置(通过 CDN 控制台配置,非命令行)
1. 缓存规则:匹配文件路径 /*/status.js,设置缓存时间为 1 秒(max-age=1);
2. 回源策略:开启「缓存过期后回源」「忽略客户端缓存」;
3. 压缩:开启 Gzip/Brotli 压缩(进一步减小文件体积);
4. 预热:活动开始前无需预热,更新后 CDN 自动回源拉取最新版本。

3. 第三步:前端页面集成(控制按钮状态)

页面中加载 status.js 并控制按钮,代码极简且高性能:

<!-- 按钮元素(提前写好禁用样式) -->
<button id="activityBtn" class="btn-disabled">立即参与活动</button>

<!-- 第一步:加载 status.js(异步加载,不阻塞页面) -->


<!-- 第二步:控制按钮的核心逻辑(几十行代码) -->

// 1. 按钮样式(提前定义,避免JS频繁修改样式)
const style = document.createElement('style');
style.textContent = `
  .btn-disabled {
    background: #ccc;
    cursor: not-allowed;
    pointer-events: none;
    opacity: 0.7;
  }
  .btn-active {
    background: #f60;
    cursor: pointer;
    pointer-events: auto;
    opacity: 1;
  }
`;
document.head.appendChild(style);

// 2. 核心函数:更新按钮状态
function updateButtonStatus() {
  const btn = document.getElementById('activityBtn');
  if (!btn) return;

  // 判断活动状态(兼容文件未加载/加载失败的情况)
  const isActive = window.activityStatus?.isActive || false;
  
  // 更新按钮样式和状态
  if (isActive) {
    btn.classList.remove('btn-disabled');
    btn.classList.add('btn-active');
    btn.disabled = false;
  } else {
    btn.classList.add('btn-disabled');
    btn.classList.remove('btn-active');
    btn.disabled = true;
  }
}

// 3. 初始化+轮询(确保活动开始瞬间生效)
// 初始化:文件加载完成后立即执行
window.addEventListener('load', updateButtonStatus);

// 轮询:每1秒重新请求 status.js 并更新状态(核心!)
setInterval(() => {
  // 动态创建 script 标签,强制重新请求(绕过浏览器缓存)
  const script = document.createElement('script');
  script.src = `https://your-cdn.com/status.js?t=${Date.now()}`; // 时间戳防缓存
  script. updateButtonStatus; // 加载完成后更新按钮
  script.onerror = () => console.warn('status.js 加载失败'); // 容错
  document.body.appendChild(script);
  // 加载后移除标签,避免DOM冗余
  setTimeout(() => document.body.removeChild(script), 1000);
}, 1000); // 与CDN缓存时间一致,1秒轮询一次

4. 第四步:活动开始时的操作(全网秒级生效)

当活动开始时,你只需要:

  1. 将服务器上的 status.js 文件内容替换为:
    window.activityStatus = {startTime: 1740000000000, isActive: true};
    
  2. 无需重启服务/刷新CDN,CDN会在1秒缓存过期后自动回源拉取最新文件;
  3. 前端页面每1秒轮询一次,拉取到最新状态后立即解锁按钮,全网用户无需刷新页面即可看到按钮变为可用状态。

三、极致优化(千万级访问场景)

  1. 减小轮询开销

    • 活动开始前可降低轮询频率(如10秒一次),活动开始前1分钟改为1秒一次;
    • 示例代码:
      let pollInterval = 10000; // 初始10秒轮询
      const preStartTime = 1739999400000; // 活动开始前1分钟的时间戳
      
      setInterval(() => {
        const now = Date.now();
        // 活动开始前1分钟,改为1秒轮询
        if (now >= preStartTime) pollInterval = 1000;
      }, 1000);
      
      // 动态调整轮询定时器
      let timer = setInterval(() => { /* 轮询逻辑 */ }, pollInterval);
      
  2. 容错处理

    • status.js 加载失败,默认保持按钮禁用状态,避免误解锁;
    • 增加时间戳兜底判断(即使JS文件更新延迟,也能按时间解锁):
      function updateButtonStatus() {
        const btn = document.getElementById('activityBtn');
        const now = Date.now();
        const startTime = window.activityStatus?.startTime || Infinity;
        const isActive = now >= startTime; // 时间戳兜底
      
        if (isActive) {
          btn.classList.remove('btn-disabled');
          btn.classList.add('btn-active');
          btn.disabled = false;
        } else {
          btn.classList.add('btn-disabled');
          btn.classList.remove('btn-active');
          btn.disabled = true;
        }
      }
      
  3. 文件体积极致压缩: 最终的 status.js 可压缩为以下形式(仅 45 字节):

    window.activityStatus={startTime:1740000000000,isActive:false}
    

总结

  1. 核心机制:通过极简的 status.js 暴露活动状态,CDN 配置1秒缓存,前端1秒轮询拉取最新文件,实现按钮状态全网秒级同步;
  2. 关键优化:时间戳兜底判断(防止JS文件更新延迟)、动态调整轮询频率(降低服务器压力)、容错处理(避免加载失败导致异常);
  3. 部署要点:活动开始前部署 isActive: false 的版本,开始时替换为 isActive: true,CDN 自动回源同步,无需额外操作。

全部评论: 0

    我有话说: