您的服務器環境和 FCM
Firebase Cloud Messaging 的服務器端由兩個組件組成:
- 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 的所有未決消息都應再次發送。