You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Gatling中模拟前端周期性Token刷新心跳机制?

可行的Token周期性刷新实现思路

这个场景太常见了——尤其是那些用户会长期挂着页面但不操作的应用(比如后台管理系统、监控面板),既要保证Token不会过期导致用户突然被踢,又不能瞎发请求浪费资源。给你几个经过实践验证的思路:

1. 基于Token过期时间的精准定时器(最推荐)

如果你的Token是JWT格式,直接解析它的exp字段就能拿到精确的过期时间。我们可以提前设置一个定时器,在Token过期前N分钟自动发起刷新请求,刷新成功后再重置定时器。这种方式完全贴合Token的生命周期,不会产生多余请求,完美匹配用户挂着页面不操作的场景。

示例代码:

let refreshTimer;

function setupTokenRefresh(token) {
  // 解析JWT的payload部分
  const payload = JSON.parse(atob(token.split('.')[1]));
  const expTimestamp = payload.exp * 1000; // 转成毫秒时间戳
  const refreshLeadTime = 5 * 60 * 1000; // 提前5分钟刷新(可根据业务调整)
  const timeToRefresh = expTimestamp - Date.now() - refreshLeadTime;

  // 清除之前的定时器,避免重复触发
  if (refreshTimer) clearTimeout(refreshTimer);

  if (timeToRefresh > 0) {
    // 设置新的刷新定时器
    refreshTimer = setTimeout(async () => {
      try {
        const response = await fetch('/api/refresh-token', {
          method: 'POST',
          credentials: 'include' // 若用HttpOnly Cookie存Refresh Token,需要这个
        });
        const newTokenData = await response.json();
        
        // 更新本地存储的Token
        localStorage.setItem('accessToken', newTokenData.accessToken);
        // 递归设置下一次刷新
        setupTokenRefresh(newTokenData.accessToken);
      } catch (error) {
        console.error('Token刷新失败:', error);
        // 刷新失败可以触发重试,或者提示用户重新登录
        handleRefreshFailure();
      }
    }, timeToRefresh);
  } else {
    // Token已经快过期或已过期,立即尝试刷新
    refreshTokenImmediately();
  }
}

// 登录成功后初始化
setupTokenRefresh(initialAccessToken);

2. 结合页面可见性API优化请求频率

用户经常会把页面切到后台(比如开着应用去干别的),这时候完全没必要继续刷新Token。用Page Visibility API监听页面状态,后台时暂停定时器,前台时重新计算剩余时间恢复刷新,能进一步减少不必要的请求:

document.addEventListener('visibilitychange', () => {
  const currentToken = localStorage.getItem('accessToken');
  if (!currentToken) return;

  if (document.hidden) {
    // 页面切后台,清除定时器
    if (refreshTimer) clearTimeout(refreshTimer);
  } else {
    // 页面回到前台,重新设置刷新定时器
    setupTokenRefresh(currentToken);
  }
});

3. 低频率心跳检查(适合非JWT场景)

如果你的Token不是JWT,没法直接解析过期时间,可以设置一个低频率的心跳定时器(比如每5分钟跑一次),每次心跳时验证Token的有效性(比如调用一个轻量的/api/check-token接口,或者读取本地存储的过期时间),如果需要刷新就发起请求。这种方式请求频率低,对服务器压力小,也符合真实用户行为:

let heartbeatTimer;

function startTokenHeartbeat() {
  heartbeatTimer = setInterval(async () => {
    const currentToken = localStorage.getItem('accessToken');
    const storedExpiry = parseInt(localStorage.getItem('tokenExpiry'), 10);
    const now = Date.now();

    // 检查是否需要刷新(比如过期前10分钟)
    if (storedExpiry && storedExpiry - now < 10 * 60 * 1000) {
      try {
        const newTokenData = await fetch('/api/refresh-token', { method: 'POST' }).then(res => res.json());
        localStorage.setItem('accessToken', newTokenData.accessToken);
        localStorage.setItem('tokenExpiry', Date.now() + newTokenData.expiresIn * 1000);
      } catch (error) {
        console.error('心跳时刷新Token失败:', error);
      }
    }
  }, 5 * 60 * 1000); // 每5分钟检查一次
}

// 启动心跳
startTokenHeartbeat();

// 页面卸载时清理定时器
window.addEventListener('beforeunload', () => {
  if (heartbeatTimer) clearInterval(heartbeatTimer);
});

额外注意事项

  • 处理刷新失败:如果刷新请求失败(比如网络问题、Refresh Token过期),要设置重试机制(比如指数退避),或者及时提示用户重新登录,避免用户在不知情的情况下操作失败。
  • 避免重复定时器:每次设置新定时器前一定要清除旧的,防止多个刷新请求同时发起。
  • 安全优先:Refresh Token一定要存在HttpOnly、Secure的Cookie里,避免XSS攻击;不要把敏感Token存在localStorage里。

内容的提问来源于stack exchange,提问作者CamHart

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:39:56