關於 FCM 消息

Firebase 雲消息傳遞 (FCM) 提供了廣泛的消息傳遞選項和功能。此頁面中的信息旨在幫助您了解不同類型的 FCM 消息以及您可以使用它們做什麼。

消息類型

使用 FCM,您可以向客戶端發送兩種類型的消息:

  • 通知消息,有時被認為是“顯示消息”。這些由 FCM SDK 自動處理。
  • 數據消息,由客戶端應用程序處理。

通知消息包含一組預定義的用戶可見鍵。相比之下,數據消息僅包含用戶定義的自定義鍵值對。通知消息可以包含可選的數據負載。兩種消息類型的最大有效負載均為 4000 字節,但從 Firebase 控制台發送消息時除外,該控制台強制執行 1024 個字符的限制。

使用場景如何發送
通知消息FCM 代表客戶端應用程序自動向最終用戶設備顯示消息。通知消息具有一組預定義的用戶可見鍵和自定義鍵值對的可選數據有效負載。
  1. Cloud Functions或您的應用服務器等可信環境中,使用Admin SDKFCM 服務器協議:設置notification密鑰。可能有可選的數據負載。始終可折疊。

    查看顯示通知和發送請求有效負載的一些示例

  2. 使用通知編輯器:輸入消息文本、標題等,然後發送。通過提供自定義數據添加可選數據負載。
數據信息客戶端應用程序負責處理數據消息。數據消息只有自定義鍵值對,沒有保留鍵名(見下文)。Cloud Functions或您的應用服務器等可信環境中,使用Admin SDKFCM 服務器協議:僅設置data密鑰。

當您希望 FCM 代表您的客戶端應用處理顯示通知時,請使用通知消息。當您想要處理客戶端應用程序上的消息時,請使用數據消息。

FCM 可以發送包含可選數據負載的通知消息。在這種情況下,FCM 處理通知負載的顯示,客戶端應用程序處理數據負載。

通知消息

對於測試或營銷和用戶重新參與,您可以使用 Firebase 控制台發送通知消息。 Firebase 控制台提供基於分析的A/B 測試,以幫助您優化和改進營銷信息。

要使用 Admin SDK 或 FCM 協議以編程方式發送通知消息,請使用通知消息的用戶可見部分的必要預定義鍵值選項集設置notification鍵。例如,這是 IM 應用程序中的 JSON 格式的通知消息。用戶可能會看到標題為“葡萄牙 vs. 丹麥”和文本“非常匹配!”的消息。在設備上:

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification":{
      "title":"Portugal vs. Denmark",
      "body":"great match!"
    }
  }
}

當應用程序在後台時,通知消息會發送到通知托盤。對於前台應用程序,消息由回調函數處理。

有關可用於構建通知消息的預定義鍵的完整列表,請參閱參考文檔:

數據信息

使用您的自定義鍵值對設置適當的鍵,以將數據負載發送到客戶端應用程序。

例如,在與上述相同的 IM 應用程序中,這是一條 JSON 格式的消息,其中信息封裝在公共data密鑰中,客戶端應用程序應解釋內容:

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "data":{
      "Nick" : "Mario",
      "body" : "great match!",
      "Room" : "PortugalVSDenmark"
    }
  }
}

上面的示例顯示了頂級或通用data字段的用法,該字段由接收消息的所有平台上的客戶端解釋。在每個平台上,客戶端應用程序都會在回調函數中接收數據負載。

數據消息加密

Android 傳輸層(請參閱FCM 架構)使用點對點加密。根據您的需要,您可以決定為數據消息添加端到端加密。 FCM 不提供端到端的解決方案。但是,有可用的外部解決方案,例如CapillaryDTLS

帶有可選數據負載的通知消息

無論是通過編程方式還是通過 Firebase 控制台,您都可以發送包含自定義鍵值對的可選負載的通知消息。在通知編輯器中,使用高級選項中的自定義數據字段。

接收包含通知和數據有效負載的消息時,應用程序的行為取決於應用程序是在後台還是前台 - 基本上,它在接收時是否處於活動狀態。

  • 在後台時,應用程序在通知托盤中接收通知負載,並且僅在用戶點擊通知時處理數據負載。
  • 在前台時,您的應用會收到一個消息對象,其中包含兩個可用的有效負載。

這是一條 JSON 格式的消息,其中包含notification鍵和data鍵:

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification":{
      "title":"Portugal vs. Denmark",
      "body":"great match!"
    },
    "data" : {
      "Nick" : "Mario",
      "Room" : "PortugalVSDenmark"
    }
  }
}

跨平台自定義消息

Firebase Admin SDK 和 FCM v1 HTTP 協議都允許您的消息請求設置message對像中的所有可用字段。這包括:

  • 所有接收消息的應用程序實例解釋的一組通用字段。
  • 特定於平台的字段集,例如AndroidConfigWebpushConfig ,僅由在指定平台上運行的應用實例解釋。

特定於平台的塊使您可以靈活地為不同平台自定義消息,以確保在收到它們時正確處理它們。 FCM 後端將考慮所有指定的參數並為每個平台定制消息。

何時使用公共字段

在以下情況下使用常用字段:

  • 針對所有平台(Apple、Android 和 Web)上的應用程序實例
  • 向主題發送消息

所有應用程序實例,無論平台如何,都可以解釋以下公共字段:

何時使用特定於平台的字段

當您需要時使用特定於平台的字段:

  • 僅將字段發送到特定平台
  • 除了公共字段之外,還發送特定於平台的字段

每當您只想將值發送到特定平台時,請不要使用公共字段;使用特定於平台的字段。例如,要僅向 Apple 平台和 Web 發送通知而不向 Android 發送通知,您必須使用兩組單獨的字段,一組用於 Apple,一組用於 Web。

當您發送具有特定傳遞選項的消息時,請使用特定於平台的字段來設置它們。如果需要,您可以為每個平台指定不同的值。但是,即使您想跨平台設置基本相同的值,您也必須使用特定於平台的字段。這是因為每個平台對該值的解釋可能略有不同——例如,在 Android 上將生存時間設置為以秒為單位的過期時間,而在 Apple 上將其設置為過期日期

示例:具有特定於平台的傳遞選項的通知消息

下面的 v1 發送請求向所有平台發送一個通用的通知標題和內容,但也發送一些特定於平台的覆蓋。具體來說,請求:

  • 為 Android 和 Web 平台設置較長的生存時間,同時將 APNs(Apple 平台)消息優先級設置為低設置
  • 設置適當的鍵來定義用戶在 Android 和 Apple 上點擊通知的結果——分別click_actioncategory
{
  "message":{
     "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
     "notification":{
       "title":"Match update",
       "body":"Arsenal goal in added time, score is now 3-0"
     },
     "android":{
       "ttl":"86400s",
       "notification"{
         "click_action":"OPEN_ACTIVITY_1"
       }
     },
     "apns": {
       "headers": {
         "apns-priority": "5",
       },
       "payload": {
         "aps": {
           "category": "NEW_MESSAGE_CATEGORY"
         }
       }
     },
     "webpush":{
       "headers":{
         "TTL":"86400"
       }
     }
   }
 }

有關消息正文中特定於平台的塊中可用鍵的完整詳細信息,請參閱HTTP v1 參考文檔。有關構建包含消息正文的發送請求的更多信息,請參閱構建發送請求

交付選項

FCM 為發送到 Android 設備的消息提供了一組特定的傳遞選項,並允許在 Apple 平台和 Web 上提供類似的選項。例如,Android 上通過 FCM 的collapse_key支持“可折疊”消息行為,Apple 上通過apns-collapse-id支持,JavaScript/Web 上通過Topic支持。有關詳細信息,請參見本節中的說明和相關參考文檔。

不可折疊和可折疊的消息

不可折疊的消息表示每個單獨的消息都被傳遞到設備。不可折疊的消息提供一些有用的內容,而不是像無內容的“ping”這樣的可折疊消息到移動應用程序以聯繫服務器以獲取數據。

不可折疊消息的一些典型用例是聊天消息或關鍵消息。例如,在 IM 應用程序中,您可能希望傳遞每條消息,因為每條消息都有不同的內容。

對於 Android,最多可以存儲 100 條消息而不會折疊。如果達到限制,則丟棄所有存儲的消息。當設備重新聯機時,它會收到一條特殊消息,指示已達到限制。然後,應用程序可以正確處理這種情況,通常是通過從應用程序服務器請求完全同步。

可折疊消息是可以被新消息替換的消息,如果它還沒有被傳遞到設備。

可折疊消息的常見用例是用於告訴移動應用從服務器同步數據的消息。一個例子是一個體育應用程序,它用最新的分數更新用戶。只有最近的消息是相關的。

要在 Android 上將消息標記為可折疊,請在消息負載中包含collapse_key參數。默認情況下,折疊鍵是在 Firebase 控制台中註冊的應用包名稱。 FCM 服務器可以同時為每個設備存儲四個不同的可折疊消息,每個消息都有一個不同的折疊鍵。如果超過這個數字,FCM 只保留四個折疊鍵,不保證保留哪些。

默認情況下,沒有負載的主題消息是可折疊的。通知消息始終是可折疊的,並且會忽略collapse_key參數。

我應該使用哪個?

從性能的角度來看,可折疊消息是更好的選擇,前提是您的應用不需要使用不可折疊消息。但是,如果您使用可折疊消息,請記住 FCM 僅允許 FCM 在任何給定時間為每個註冊令牌使用最多四個不同的折疊密鑰。您不得超過此數量,否則可能會導致不可預知的後果。

使用場景如何發送
不可折疊每條消息對客戶端應用程序都很重要,需要傳遞。除通知消息外,默認情況下所有消息都是不可折疊的。
可折疊當有新消息呈現與客戶端應用程序無關的舊消息時,FCM 會替換舊消息。例如:用於從服務器啟動數據同步的消息,或過時的通知消息。在您的消息請求中設置適當的參數:
  • 安卓上的collapseKey
  • 蘋果上apns-collapse-id
  • 網絡Topic
  • 舊協議中的collapse_key (所有平台)

設置消息的優先級

為下游消息分配傳遞優先級有兩種選擇:正常優先級和高優先級。儘管不同平台的行為略有不同,但正常和高優先級消息的傳遞方式如下:

  • 正常優先。當應用程序處於前台時,會立即傳遞普通優先級消息。對於後台應用程序,交付可能會延遲。對於時間敏感度較低的消息,例如新電子郵件通知、保持 UI 同步或在後台同步應用程序數據,請選擇正常傳遞優先級。

  • 高優先級。即使設備處於打盹模式,FCM 也會嘗試立即傳遞高優先級消息。高優先級消息用於時間敏感、用戶可見的內容。

以下是通過 FCM HTTP v1 協議發送的普通優先級消息示例,用於通知雜誌訂閱者有新內容可供下載:

{
  "message":{
    "topic":"subscriber-updates",
    "notification":{
      "body" : "This week's edition is now available.",
      "title" : "NewsMagazine.com",
    },
    "data" : {
      "volume" : "3.21.15",
      "contents" : "http://www.news-magazine.com/world-week/21659772"
    },
    "android":{
      "priority":"normal"
    },
    "apns":{
      "headers":{
        "apns-priority":"5"
      }
    },
    "webpush": {
      "headers": {
        "Urgency": "high"
      }
    }
  }
}

有關設置消息優先級的更多特定於平台的詳細信息:

設置消息的生命週期

FCM 通常在消息發送後立即傳遞消息。但是,這可能並不總是可能的。例如,如果平台是 Android,則設備可能會關閉、離線或不可用。或者 FCM 可能會故意延遲消息,以防止應用消耗過多資源並對電池壽命產生負面影響。

發生這種情況時,FCM 會存儲消息並在可行時盡快交付。雖然這在大多數情況下都很好,但有些應用程序可能永遠不會發送遲到的消息。例如,如果消息是來電或視頻聊天通知,則它僅在通話終止前的短時間內有意義。或者,如果該消息是一個活動的邀請,如果在活動結束後收到它是沒有用的。

在 Android 和 Web/JavaScript 上,您可以指定消息的最長生命週期。該值必須是從 0 到 2,419,200 秒(28 天)的持續時間,它對應於 FCM 存儲和嘗試傳遞消息的最長時間。不包含此字段的請求默認為最長 4 週。

以下是此功能的一些可能用途:

  • 視頻聊天來電
  • 即將到期的邀請活動
  • 日曆事件

指定消息生命週期的另一個優點是 FCM 從不限制生存時間值為 0 秒的消息。換句話說,FCM 保證“現在或永遠”必須傳遞的消息盡最大努力。請記住, time_to_live值為 0 意味著無法立即傳遞的消息將被丟棄。但是,由於此類消息從不存儲,因此這為發送通知消息提供了最佳延遲。

下面是一個包含 TTL 的請求示例:

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "data":{
      "Nick" : "Mario",
      "body" : "great match!",
      "Room" : "PortugalVSDenmark"
    },
    "apns":{
      "headers":{
        "apns-expiration":"1604750400"
      }
    },
    "android":{
      "ttl":"4500s"
    },
    "webpush":{
      "headers":{
        "TTL":"4500"
      }
    }
  }
}

接收來自多個發件人的消息

FCM 允許多方向同一個客戶端應用程序發送消息。例如,假設客戶端應用程序是具有多個貢獻者的文章聚合器,並且每個貢獻者都應該能夠在發布新文章時發送消息。此消息可能包含一個 URL,以便客戶端應用程序可以下載文章。 FCM 無需將所有發送活動集中在一個位置,而是讓您能夠讓這些貢獻者中的每一個發送自己的消息。

要啟用此功能,請確保您擁有每個發件人的發件人 ID 。請求註冊時,客戶端應用程序多次獲取令牌,每次在受眾字段中使用不同的發件人 ID,使用給定平台的令牌檢索方法:

確保不要將多個發件人 ID 添加到單個令牌請求中,因為這可能會產生不可預知的結果。分別撥打每個電話,每個發件人 ID 一次。

最後,與相應的發件人共享註冊令牌,他們將能夠使用自己的身份驗證密鑰向客戶端應用程序發送消息。

請注意,有 100 個多個發件人的限制。

消息的生命週期

當應用服務器向 FCM 發布消息並接收到消息 ID 時,並不意味著該消息已傳遞到設備。相反,這意味著它已被接受交付。消息被接受後會發生什麼取決於許多因素。

在最好的情況下,如果設備連接到 FCM,屏幕打開並且沒有限制限制,則消息會立即傳遞。

如果設備已連接但處於打盹狀態,則 FCM 會存儲一條低優先級消息,直到設備處於打盹狀態。這就是collapse_key標誌發揮作用的地方:如果已經存儲了具有相同折疊密鑰(和註冊令牌)並等待傳遞的消息,則舊消息將被丟棄,新消息取而代之(即舊消息)消息被新消息折疊)。但是,如果未設置折疊鍵,則新舊消息都將被存儲以供將來傳遞。

如果設備未連接到 FCM,則將存儲消息,直到建立連接(再次遵守折疊密鑰規則)。建立連接後,FCM 會將所有未決消息傳送到設備。如果設備不再連接(例如,如果它已恢復出廠設置),則消息最終會超時並從 FCM 存儲中丟棄。默認超時為四個星期,除非設置了time_to_live標誌。

要更深入地了解消息的傳遞:

    要更深入地了解 Android 或 Apple 平台上的消息傳遞,請參閱FCM 報告儀表板,它記錄了在 Apple 和 Android 設備上發送和打開的消息數量,以及“印像數”(用戶看到的通知)的數據安卓應用。

對於啟用了直接通道消息的 Android 設備,如果設備超過一個月未連接 FCM,FCM 仍會接受該消息,但會立即丟棄該消息。如果設備在您發送給它的最後一條數據消息的四個星期內連接,您的客戶端會收到onDeletedMessages()回調。然後,應用程序可以正確處理這種情況,通常是通過從應用程序服務器請求完全同步。

最後,當 FCM 嘗試向設備傳遞消息並且應用程序被卸載時,FCM 會立即丟棄該消息並使註冊令牌無效。以後嘗試向該設備發送消息會導致NotRegistered錯誤。

節流和縮放

我們的目標是始終傳遞通過 FCM 發送的每條消息。但是,傳遞每條消息有時會導致整體用戶體驗不佳。在其他情況下,我們需要提供邊界以確保 FCM 為所有發送者提供可擴展的服務。

可折疊消息限制

如上所述,可折疊消息是設計為相互折疊的無內容通知。如果開發人員過於頻繁地向應用重複相同的消息,我們會延遲(限制)消息以減少對用戶電池的影響。

例如,如果您向單個設備發送大量新的電子郵件同步請求,我們可能會將下一個電子郵件同步請求延遲幾分鐘,以便該設備可以以較低的平均速率進行同步。嚴格執行此節流以限制用戶體驗到的電池影響。

如果您的用例需要高突發發送模式,那麼不可折疊消息可能是正確的選擇。對於此類消息,請確保在此類消息中包含內容,以降低電池成本。

我們將可折疊消息限制為每台設備的每個應用最多 20 條消息,每 3 分鐘補充 1 條消息。

XMPP 服務器限制

我們將您可以連接到 FCM XMPP 服務器的速率限制為每個項目每分鐘 400 個連接。這不應該是消息傳遞的問題,但對於確保我們系統的穩定性很重要。

對於每個項目,FCM 允許並行連接 2500 個。

單個設備的最大消息速率

您可以向單個設備發送多達 240 條消息/分鐘和 5,000 條消息/小時。這個高閾值意味著允許短期流量突發,例如當用戶通過聊天快速交互時。此限制可防止發送邏輯中的錯誤無意中耗盡設備上的電池。

上行消息限制

我們將每個項目的上游消息限制為 1,500,000/分鐘,以避免上游目標服務器過載。

我們將每台設備的上游消息限制為每分鐘 1,000 條,以防止電池因不良應用行為而耗盡。

主題消息限制

主題訂閱添加/刪除速率限制為每個項目 3,000 QPS。

有關消息發送速率,請參閱Fanout Throttling

扇出節流

消息扇出是將消息發送到多個設備的過程,例如當您定位主題和組時,或者當您使用通知編輯器定位受眾或用戶細分時。

消息扇出不是即時的,因此有時您會同時進行多個扇出。我們將每個項目的並發消息扇出數限制為 1,000。之後,我們可能會拒絕額外的扇出請求或推遲請求的扇出,直到一些已經在進行中的扇出完成。

實際可實現的扇出率受同時請求扇出的項目數量的影響。單個項目的扇出率 10,000 QPS 並不少見,但這個數字並不是保證,而是系統總負載的結果。需要注意的是,可用的扇出容量在項目之間而不是在扇出請求之間分配。因此,如果您的項目有兩個正在進行中的扇出,那麼每個扇出只會看到可用扇出率的一半。最大化扇出速度的推薦方法是一次只進行一個活動扇出。

FCM 端口和防火牆

如果您的組織有防火牆來限制進出 Internet 的流量,您需要將其配置為允許移動設備與 FCM 連接,以便您網絡上的設備接收消息。 FCM 通常使用端口 5228,但有時使用 443、5229 和 5230。

對於連接到您網絡上的設備,FCM 不提供特定 IP,因為我們的 IP 範圍更改過於頻繁,您的防火牆規則可能會過時,從而影響您的用戶體驗。理想情況下,白名單端口 5228-5230 和 443 沒有 IP 限制。但是,如果您必須有 IP 限制,則應將goog.json中列出的所有 IP 地址列入白名單。這個龐大的列表會定期更新,建議您每月更新一次規則。由防火牆 IP 限制引起的問題通常是間歇性的並且難以診斷。

我們確實提供了一組可以列入白名單的域名,而不是 IP 地址。下面列出了這些主機名。如果我們開始使用其他主機名,我們將在此處更新列表。為您的防火牆規則使用域名可能會或可能不會在您的防火牆設備中起作用。

要打開的 TCP 端口:

  • 5228
  • 5229
  • 5230
  • 443

要打開的主機名:

  • mtalk.google.com
  • mtalk4.google.com
  • mtalk-staging.google.com
  • mtalk-dev.google.com
  • alt1-mtalk.google.com
  • alt2-mtalk.google.com
  • alt3-mtalk.google.com
  • alt4-mtalk.google.com
  • alt5-mtalk.google.com
  • alt6-mtalk.google.com
  • alt7-mtalk.google.com
  • alt8-mtalk.google.com
  • android.apis.google.com
  • device-provisioning.googleapis.com
  • firebaseinstallations.googleapis.com

網絡地址轉換和/或狀態包檢查防火牆:

如果您的網絡實施網絡地址轉換 (NAT) 或狀態數據包檢查 (SPI),請為我們通過端口 5228-5230 的連接實施 30 分鐘或更長的超時。這使我們能夠提供可靠的連接,同時減少用戶移動設備的電池消耗。

證書

根據您實施的 FCM 功能,您可能需要 Firebase 項目中的以下憑據:

項目編號您的 Firebase 項目的唯一標識符,用於對 FCM v1 HTTP 端點的請求。此值在Firebase 控制台設置窗格中可用。
註冊令牌

標識每個客戶端應用程序實例的唯一令牌字符串。單個設備和設備組消息傳遞需要註冊令牌。請注意,註冊令牌必須保密。

發件人ID創建 Firebase 項目時創建的唯一數值,可在 Firebase 控制台“設置”窗格的“雲消息傳遞”選項卡中找到。發件人 ID 用於標識可以向客戶端應用程序發送消息的每個發件人。
訪問令牌一種短期 OAuth 2.0 令牌,用於授權對 HTTP v1 API 的請求。此令牌與屬於您的 Firebase 項目的服務帳號相關聯。要創建和輪換訪問令牌,請按照授權發送請求中描述的步驟進行操作。
服務器密鑰(用於舊協議)

授權您的應用服務器訪問 Google 服務的服務器密鑰,包括通過 Firebase 雲消息傳遞舊協議發送消息。您在創建 Firebase 項目時獲取服務器密鑰。您可以在 Firebase 控制台設置窗格的雲消息傳遞選項卡中查看它。

重要提示:請勿在客戶端代碼中的任何位置包含服務器密鑰。此外,請確保僅使用服務器密鑰來授權您的應用服務器。 FCM 拒絕 Android、Apple 平台和瀏覽器密鑰。