Firebase 雲消息傳遞的服務器端由兩個組件組成:
- Google 提供的FCM 後端。
- 您的應用服務器或運行服務器邏輯的其他受信任的服務器環境,例如Cloud Functions for Firebase或由 Google 管理的其他雲環境。
您的應用服務器或受信任的服務器環境將消息請求發送到 FCM 後端,然後將消息路由到在用戶設備上運行的客戶端應用程序。
可信服務器環境的要求
您的應用服務器環境必須滿足以下條件:
- 能夠向 FCM 後端發送格式正確的消息請求。
- 能夠處理請求並使用指數退避重新發送它們。
- 能夠安全地存儲服務器授權憑證和客戶端註冊令牌。
- 對於 XMPP 協議(如果使用),服務器必須能夠生成消息 ID 以唯一標識它發送的每條消息(FCM HTTP 後端生成消息 ID 並在響應中返回它們)。每個發件人 ID 的 XMPP 消息 ID 應該是唯一的。
選擇服務器選項
您需要決定與 FCM 服務器交互的方式:使用Firebase Admin SDK或原始協議。由於它支持流行的編程語言以及處理身份驗證和授權的便捷方法,因此推薦使用 Firebase Admin SDK。
與 FCM 服務器交互的選項包括:- Firebase Admin SDK,支持Node 、 Java 、 Python 、 C#和Go 。
- FCM HTTP v1 API是最新的協議選項,具有更安全的授權和靈活的跨平台消息傳遞功能(Firebase Admin SDK 基於此協議並提供其所有固有優勢)。由於新功能通常僅添加到 HTTP v1 API,因此我們建議在大多數用例中使用此 API。
- 舊的 HTTP協議。強烈建議新項目採用 FCM v1 HTTP API 而不是舊協議。
- 舊版 XMPP服務器協議。強烈建議新項目採用 FCM v1 HTTP API 而不是舊協議。
適用於 FCM 的 Firebase 管理員 SDK
Admin FCM API 處理與後端的身份驗證,並有助於發送消息和管理主題訂閱。使用 Firebase Admin SDK,您可以:
- 向單個設備發送消息
- 向匹配一個或多個主題的主題和條件語句發送消息。
- 為設備訂閱和取消訂閱主題
- 構建針對不同目標平台量身定制的消息負載
Admin Node.js SDK 提供了向設備組發送消息的方法。
要設置 Firebase Admin SDK,請參閱將 Firebase Admin SDK 添加到您的服務器。如果您已有 Firebase 項目,請從添加 SDK開始。此外,請確保在您的項目的雲消息設置頁面中啟用雲消息 API。然後,一旦安裝了 Firebase Admin SDK,您就可以開始編寫邏輯來構建發送請求。
FCM 服務器協議
目前 FCM 提供以下原始服務器協議:
您的應用服務器可以單獨或串聯使用這些協議。因為它是向多個平台發送消息的最新且最靈活的,所以在可行的情況下建議使用 FCM HTTP v1 API。如果您的要求包括從設備到服務器的上游消息傳遞,則需要實現 XMPP 協議。
XMPP 消息傳遞與 HTTP 消息傳遞在以下方面不同:
- 上游/下游消息
- HTTP:僅限下游,雲到設備。
- XMPP:上游和下游(設備到雲、雲到設備)。
- 消息傳遞(同步或異步)
- HTTP:同步的。應用服務器將消息作為 HTTP POST 請求發送並等待響應。這種機制是同步的,並阻止發送方發送另一條消息,直到收到響應。
- XMPP:異步。應用服務器通過持久的 XMPP 連接以全線速向所有設備發送/接收消息。 XMPP 連接服務器異步發送確認或失敗通知(以特殊 ACK 和 NACK JSON 編碼的 XMPP 消息的形式)。
- JSON
- HTTP:作為 HTTP POST 發送的 JSON 消息。
- XMPP:封裝在 XMPP 消息中的 JSON 消息。
- 純文本
- HTTP:作為 HTTP POST 發送的純文本消息。
- XMPP:不支持。
- 多播下行發送到多個註冊令牌。
- HTTP:支持 JSON 消息格式。
- XMPP:不支持。
實現 HTTP 服務器協議
為了發送消息,應用服務器發出一個 POST 請求,其中包含一個 HTTP 標頭和一個由 JSON 鍵值對組成的 HTTP 正文。有關標頭和正文選項的詳細信息,請參閱構建應用服務器發送請求
實現 XMPP 服務器協議
FCM 消息的 JSON 有效負載類似於 HTTP 協議,但有以下例外:
- 不支持多個收件人。
- FCM 添加字段
message_id
,這是必需的。此 ID 唯一標識 XMPP 連接中的消息。來自 FCM 的 ACK 或 NACK 使用message_id
來標識從應用服務器發送到 FCM 的消息。因此,重要的是這個message_id
不僅是唯一的(每個發件人 ID ),而且始終存在。 - XMPP 使用服務器密鑰來授權與 FCM 的持久連接。有關詳細信息,請參閱授權發送請求。
除了常規 FCM 消息外,還會發送控制消息,由 JSON 對像中的message_type
字段指示。該值可以是“ack”或“nack”,或“control”(請參閱下面的格式)。您的服務器可以忽略任何帶有未知message_type
的 FCM 消息。
對於您的應用服務器從 FCM 接收到的每條設備消息,它都需要發送一個 ACK 消息。它永遠不需要發送 NACK 消息。如果您沒有為消息發送 ACK,FCM 會在下一次建立新的 XMPP 連接時重新發送它,除非消息首先過期。
FCM 還為每個服務器到設備的消息發送一個 ACK 或 NACK。如果您也沒有收到,則表示 TCP 連接在操作過程中關閉,您的服務器需要重新發送消息。有關詳細信息,請參閱流控制。
有關所有消息參數的列表,請參閱協議參考。
請求格式
帶有有效負載的消息 - 通知消息
這是通知消息的 XMPP 節:
<message id=""> <gcm xmlns="google:mobile:data"> { "to":"REGISTRATION_ID", // "to" replaces "registration_ids" "notification": { "title": "Portugal vs. Denmark”, "body”: "5 to 1” }, "time_to_live":"600" } </gcm> </message>
帶有有效負載的消息 - 數據消息
這是一個 XMPP 節,其中包含從應用服務器到 FCM 的 JSON 消息:
<message id=""> <gcm xmlns="google:mobile:data"> { "to":"REGISTRATION_ID", // "to" replaces "registration_ids" "message_id":"m-1366082849205" // new required field "data": { "hello":"world", } "time_to_live":"600", } </gcm> </message>
響應格式
FCM 響應可以有三種可能的形式。第一個是常規的“確認”消息。但是當響應包含錯誤時,消息可以採用 2 種不同的形式,如下所述。
確認消息
這是一個 XMPP 節,其中包含從 FCM 到應用服務器的 ACK/NACK 消息:
<message id=""> <gcm xmlns="google:mobile:data"> { "from":"REGID", "message_id":"m-1366082849205" "message_type":"ack" } </gcm> </message>
NACK 消息
NACK 錯誤是一條常規 XMPP 消息,其中message_type
狀態消息為“nack”。 NACK 消息包含:
- NACK 錯誤代碼。
- NACK 錯誤描述。
下面是一些例子。
註冊不良:
<message> <gcm xmlns="google:mobile:data"> { "message_type":"nack", "message_id":"msgId1", "from":"SomeInvalidRegistrationToken", "error":"BAD_REGISTRATION", "error_description":"Invalid token on 'to' field: SomeInvalidRegistrationId" } </gcm> </message>
無效的 JSON:
<message> <gcm xmlns="google:mobile:data"> { "message_type":"nack", "message_id":"msgId1", "from":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...", "error":"INVALID_JSON", "error_description":"InvalidJson: JSON_TYPE_ERROR : Field \"time_to_live\" must be a JSON java.lang.Number: abc" } </gcm> </message>
超出設備消息速率:
<message id="..."> <gcm xmlns="google:mobile:data"> { "message_type":"nack", "message_id":"msgId1", "from":"REGID", "error":"DEVICE_MESSAGE_RATE_EXCEEDED", "error_description":"Downstream message rate exceeded for this registration id" } </gcm> </message>
有關 NACK 錯誤代碼的完整列表,請參閱服務器參考。除非另有說明,否則不應重試 NACKed 消息。應將意外的 NACK 錯誤代碼視為與INTERNAL_SERVER_ERROR
相同。
節錯誤
在某些情況下,您也可能會收到節錯誤。一個節錯誤包含:
- 節錯誤代碼。
- 節錯誤描述(自由文本)。
例如:
<message id="3" type="error" to="123456789@fcm.googleapis.com/ABC"> <gcm xmlns="google:mobile:data"> {"random": "text"} </gcm> <error code="400" type="modify"> <bad-request xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/> <text xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"> InvalidJson: JSON_PARSING_ERROR : Missing Required Field: message_id\n </text> </error> </message>
控制消息
FCM 需要定期關閉連接以執行負載平衡。在它關閉連接之前,FCM 會發送一個CONNECTION_DRAINING
消息來指示連接正在耗盡並且將很快關閉。 “Draining”是指關閉進入連接的消息流,但允許管道中已經存在的任何內容繼續。當您收到CONNECTION_DRAINING
消息時,您應該立即開始向另一個 FCM 連接發送消息,並在必要時打開一個新連接。但是,您應該保持原始連接打開並繼續接收可能來自連接的消息(並確認它們) - FCM 在準備好時處理啟動連接關閉。
CONNECTION_DRAINING
消息如下所示:
<message> <data:gcm xmlns:data="google:mobile:data"> { "message_type":"control" "control_type":"CONNECTION_DRAINING" } </data:gcm> </message>
CONNECTION_DRAINING
是當前唯一支持的control_type
。
流量控制
發送到 FCM 的每條消息都會收到一個 ACK 或一個 NACK 響應。未收到這些響應之一的消息被視為待處理。如果掛起的消息計數達到 100,應用服務器應停止發送新消息並等待 FCM 確認一些現有的掛起消息,如圖 1 所示:

圖 1.消息/確認流。
相反,為了避免應用服務器過載,如果未確認的消息太多,FCM 會停止發送。因此,應用服務器應盡快“確認”通過 FCM 從客戶端應用程序接收到的上游消息,以保持傳入消息的恆定流。上述待處理消息限制不適用於這些 ACK。即使待處理的消息計數達到 100,應用服務器也應繼續為從 FCM 接收到的消息發送 ACK,以避免阻止新上游消息的傳遞。
ACK 僅在一個連接的上下文中有效。如果在確認消息之前連接已關閉,則應用服務器應等待 FCM 重新發送上游消息,然後再再次確認。同樣,在連接關閉之前未從 FCM 收到 ACK/NACK 的所有未決消息應再次發送。