Join us in person and online for Firebase Summit on October 18, 2022. Learn how Firebase can help you accelerate app development, release your app with confidence, and scale with ease. Register now
透過集合功能整理內容 你可以依據偏好儲存及分類內容。

您的服務器環境和 FCM

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,支持NodeJavaPythonC#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 所示:

FCM與app server之間的控制流程詳圖

圖 1.消息/確認流。

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

ACK 僅在一個連接的上下文中有效。如果在確認消息之前連接已關閉,則應用服務器應等待 FCM 重新發送上游消息,然後再再次確認。同樣,在連接關閉之前未從 FCM 收到 ACK/NACK 的所有未決消息應再次發送。