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

如何实现可调用Google Cloud Function幂等性 解决FCM重复通知问题

问题描述

我部署了一个用于向Firebase主题推送通知的Google Cloud Function,该函数此前运行稳定,近期突然出现同一时间重复发送2-3条通知的异常。联系Firebase支持团队后,对方建议我将函数改造为幂等函数,但我不清楚针对可调用类型的云函数该如何实现,函数实现代码如下:

更新2

经确认该问题属于Admin SDK的已知Bug,官方已在最新发布版本中完成修复。

更新

我此前误以为该事件驱动型函数本身已具备幂等性,函数日志可证明函数逻辑仅执行一次。经过两个月的反复排查,最终确认问题根源为Firebase Admin SDK的默认重试机制:代码中调用的getMessaging().sendToTopic()方法在抛出错误终止函数前,会自动重试4次,加上原始请求共计发起5次推送请求。

重复通知的产生原因是:Admin SDK偶尔会因异常无法连通FCM服务器,在向所有主题订阅者推送的过程中(或尚未完成全量推送时)抛出错误,随后会从头开始重试全量推送,导致部分用户仅收到1条通知,部分用户收到2-4条重复通知。

目前我尚未找到禁用该默认重试机制、或实现推送失败断点续传的方案(后续将针对该问题单独提问),现阶段采用了客户端侧的简易去重方案:移动端若在1分钟内收到多条内容相同的通知,仅展示1条。

原函数实现代码

const functions = require("firebase-functions");

// 引入Firebase Admin SDK用于访问Firestore
const admin = require("firebase-admin");
const {getMessaging} = require("firebase-admin/messaging");
const serviceAccount = require("./serviceAccountKey.json");

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: "https://mylinktodatabase.firebaseio.com",
});

exports.callNotification = functions.https.onCall( (data) => {
  // 获取传入参数
  const indicator = data.indicator;
  const mTitle = data.title;
  const mBody = data.body;
  // 推送目标主题
  const topic = "mytopic";
  const options = {
    "priority": "high",
    "timeToLive": 3600,
  };
  let message;
  if (indicator != null ) {
    message = {
      data: {
        ind: indicator,
      },
    };
  } else {
    message = {
      data: {
        title: mTitle,
        body: mBody,
      },
    };
  }

  // 向订阅了指定主题的设备推送消息
  return getMessaging().sendToTopic(topic, message, options)
      .then(() => {
        if (indicator != null ) {
          console.log("Successfully sent message");
          return {
            result: "Successfully sent message", status: 200};
        } else {
          console.log("Successfully sent custom");
          return {
            result: "Successfully sent custom", status: 200};
        }
      })
      .catch((error) => {
        if (indicator != null ) {
          console.log("Error sending message:", error);
          return {result: `Error sending message: ${error}`, status: 500};
        } else {
          console.log("Error sending custom:", error);
          return {result: `Error sending custom: ${error}`, status: 500};
        }
      });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 23:15:11