Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

您的服務器環境和 FCM

Firebase Cloud Messaging 的服務器端由兩個組件組成:

  • 由谷歌提供的FCM後端
  • 你的應用服務器或您的服務器的邏輯運行,如其他受信任的服務器環境的雲功能的火力地堡或其他雲環境由谷歌管理。

您的應用服務器或受信任的服務器環境將消息請求發送到 FCM 後端,然後將消息路由到在用戶設備上運行的客戶端應用程序。

可信服務器環境要求

您的應用服務器環境必須滿足以下條件:

  • 能夠向 FCM 後端發送格式正確的消息請求。
  • 能夠處理請求並用重發這些指數回退。
  • 能夠安全地存儲服務器授權憑據和客戶端註冊令牌。
  • 對於 XMPP 協議(如果使用),服務器必須能夠生成消息 ID 以唯一標識它發送的每條消息(FCM HTTP 後端生成消息 ID 並在響應中返回它們)。每個發件人 ID 的 XMPP 消息 ID 應該是唯一的。

選擇服務器選項

你需要一個方式決定與FCM服務器進行交互:無論是使用火力地堡管理員SDK或原始協議。由於 Firebase Admin SDK 支持流行的編程語言以及處理身份驗證和授權的便捷方法,因此推薦使用 Firebase Admin SDK。

與 FCM 服務器交互的選項包括:
  • 在火力地堡管理員SDK,這對於支持節點Java的的PythonC#圍棋
  • FCM HTTP 1.0版API ,這是最先進的的協議選項日期,以更安全的授權和靈活的跨平台的通訊能力(在火力地堡管理SDK基於該協議,並提供其所有的固有優勢)。
  • 遺留HTTP協議。
  • XMPP服務器協議。請注意,如果您想使用來自客戶端應用程序的上游消息傳遞,則必須使用 XMPP。

適用於 FCM 的 Firebase Admin SDK

Admin FCM API 處理與後端的身份驗證並促進發送消息和管理主題訂閱。使用 Firebase Admin SDK,您可以:

  • 向單個設備發送消息
  • 向與一個或多個主題匹配的主題和條件語句發送消息。
  • 在主題中訂閱和取消訂閱設備
  • 構建適合不同目標平台的消息負載

Admin Node.js SDK 提供了向設備組發送消息的方法。

要設置管理員火力地堡SDK,請參閱添加火力地堡管理員SDK到您的服務器。如果你已經有了一個火力地堡項目,開始添加SDK 。然後,一旦安裝了火力地堡管理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 服務器協議

為了發送消息,應用服務器發出一個帶有 HTTP 標頭和由 JSON 鍵值對組成的 HTTP 正文的 POST 請求。有關標題和正文選項的詳細信息,請參閱構建應用服務器發送請求

實現 XMPP 服務器協議

FCM 消息的 JSON 有效負載類似於 HTTP 協議,但有以下例外:

  • 不支持多個收件人。
  • FCM增加了現場message_id ,這是必需的。此 ID 唯一標識 XMPP 連接中的消息。從FCM的ACK或NACK使用message_id來識別從應用服務器發送到FCM的消息。因此,重要的是這個message_id不僅是(每唯一發件人ID ),但始終存在。
  • XMPP 使用服務器密鑰來授權與 FCM 的持久連接。見授權發送請求以獲取更多信息。

除了常規的FCM消息,控制消息被發送,由所指示的message_type在JSON對象字段。該值可以是“ack”或“nack”,或“control”(參見下面的格式)。與未知的任何消息FCM message_type可以通過你的服務器被忽略。

對於您的應用服務器從 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錯誤代碼的完整列表。除非另有說明,否則不應重試 NACK 消息。意外的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消息表明連接被耗盡,即將關閉。 “耗盡”是指關閉進入連接的消息流,但允許管道中已經存在的任何內容繼續。當您收到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 所示:

FCM與應用服務器控制流程詳圖

圖1.消息/ ACK流動。

相反,為了避免應用服務器過載,如果有太多未確認的消息,FCM 會停止發送。因此,應用服務器應盡快“確認”通過 FCM 從客戶端應用程序接收到的上游消息,以保持傳入消息的恆定流。上述未決消息限制不適用於這些 ACK。即使待處理消息計數達到 100,應用程序服務器也應繼續為從 FCM 接收的消息發送 ACK,以避免阻止新上游消息的傳遞。

ACK 僅在一個連接的上下文中有效。如果連接在消息可以被確認之前關閉,應用服務器應該等待 FCM 重新發送上游消息,然後再次確認它。類似地,在連接關閉之前未從 FCM 收到 ACK/NACK 的所有未決消息都應再次發送。