Catch up on everything announced at Firebase Summit, and learn how Firebase can help you accelerate app development and run your app with confidence. Learn More
透過集合功能整理內容 你可以依據偏好儲存及分類內容。

您的服務器環境和 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,支持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與應用服務器之間的控制流程詳圖

圖 1.消息/確認流。

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

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