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

Firebase Admin NodeJS SDK发送FCM消息遇无效令牌超时求助

解决Firebase Admin SDK发送FCM到失效令牌时Lambda超时问题

核心原因

失效的FCM令牌会导致admin.messaging().send()方法在Lambda环境下底层HTTP请求卡住,无法触发Promise的resolve/reject,常规try-catch无法捕获,最终导致Lambda超时。

解决方案

1. 给FCM发送方法添加手动超时包装

通过Promise.race将send请求和超时Promise绑定,强制在指定时间内结束请求,避免无限挂起:

const admin = require('firebase-admin');

// 包装send方法,添加超时逻辑
const sendFcmWithTimeout = async (message, timeoutMs = 10000) => {
  const timeoutPromise = new Promise((_, reject) => {
    setTimeout(() => reject(new Error('FCM请求超时')), timeoutMs);
  });
  // 竞速执行send请求和超时逻辑
  return Promise.race([admin.messaging().send(message), timeoutPromise]);
};

// 业务代码中调用
exports.handler = async (event) => {
  const msg = {
    token: '失效的FCM令牌',
    notification: { title: '测试消息', body: '内容' }
  };

  try {
    await sendFcmWithTimeout(msg);
    return { statusCode: 200, body: '发送成功' };
  } catch (error) {
    console.error('FCM处理失败:', error.message);
    // 针对超时或令牌错误做后续处理
    if (error.message.includes('超时')) {
      // 可标记该令牌疑似失效,后续验证
    }
    return { statusCode: 500, body: '发送失败' };
  }
};

2. 发送前提前验证令牌有效性

利用admin.messaging().validateToken()提前检查令牌状态,直接过滤失效令牌,避免进入send流程:

exports.handler = async (event) => {
  const targetToken = '待验证的FCM令牌';
  const msg = {
    token: targetToken,
    notification: { title: '测试消息', body: '内容' }
  };

  try {
    // 先验证令牌有效性
    await admin.messaging().validateToken(targetToken);
    // 验证通过再发送
    await admin.messaging().send(msg);
    return { statusCode: 200, body: '发送成功' };
  } catch (error) {
    // 处理令牌失效类错误
    if (['messaging/invalid-registration-token', 'messaging/registration-token-not-registered'].includes(error.code)) {
      console.log('令牌已失效,移除:', targetToken);
      // 这里更新数据库,删除该失效令牌,避免后续重复发送
    } else {
      console.error('发送错误:', error);
    }
    return { statusCode: 500, body: '处理失败' };
  }
};

3. 配置SDK的HTTP客户端超时

初始化Firebase Admin SDK时,设置HTTP/HTTPS客户端的超时时间,从底层限制请求时长:

const admin = require('firebase-admin');
const http = require('http');
const https = require('https');

// 创建带超时配置的HTTP/HTTPS代理
const httpAgent = new http.Agent({ 
  keepAlive: true, 
  timeout: 5000 // 5秒超时
});
const httpsAgent = new https.Agent({ 
  keepAlive: true, 
  timeout: 5000 
});

// 初始化SDK时传入代理配置
admin.initializeApp({
  credential: admin.credential.applicationDefault(),
  httpAgent: httpAgent,
  httpsAgent: httpsAgent
});

关键注意事项

  • 当捕获到messaging/registration-token-not-registered错误时,一定要从数据库中移除该令牌,避免后续重复触发相同问题。
  • 超时时间建议设置为10秒以内,适配Lambda的30秒超时上限,预留足够时间处理其他业务逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 01:12:03