Ihre Serverumgebung und FCM

Die Serverseite von Firebase Cloud Messaging besteht aus zwei Komponenten:

  • Das von Google bereitgestellte FCM-Back- End.
  • Ihr App-Server oder eine andere vertrauenswürdige Serverumgebung, in der Ihre Serverlogik ausgeführt wird, z. B. Cloud Functions for Firebase oder andere von Google verwaltete Cloud-Umgebungen.

Ihr App-Server oder Ihre vertrauenswürdige Serverumgebung sendet Nachrichtenanforderungen an das FCM-Back-End, das Nachrichten dann an Client-Apps weiterleitet, die auf den Geräten der Benutzer ausgeführt werden.

Anforderungen an die vertrauenswürdige Serverumgebung

Ihre App-Server-Umgebung muss die folgenden Kriterien erfüllen:

  • Kann ordnungsgemäß formatierte Nachrichtenanforderungen an das FCM-Backend senden.
  • Kann Anfragen verarbeiten und sie mit exponentiellem Backoff erneut senden.
  • Kann Anmeldeinformationen für die Serverautorisierung und Token für die Clientregistrierung sicher speichern.
  • Für das XMPP-Protokoll (falls verwendet) muss der Server in der Lage sein, Nachrichten-IDs zu generieren, um jede von ihm gesendete Nachricht eindeutig zu identifizieren (das FCM-HTTP-Backend generiert Nachrichten-IDs und gibt sie in der Antwort zurück). XMPP-Nachrichten-IDs sollten pro Absender-ID eindeutig sein.

Auswählen einer Serveroption

Sie müssen sich für eine Methode zur Interaktion mit FCM-Servern entscheiden: entweder mit dem Firebase Admin SDK oder den Raw-Protokollen. Aufgrund seiner Unterstützung für gängige Programmiersprachen und seiner praktischen Methoden zur Handhabung der Authentifizierung und Autorisierung ist das Firebase Admin SDK die empfohlene Methode.

Zu den Optionen für die Interaktion mit FCM-Servern gehören die folgenden:
  • Das Firebase Admin SDK, das Node , Java , Python , C# und Go unterstützt.
  • Die FCM HTTP v1 API , die aktuellste der Protokolloptionen, mit sichererer Autorisierung und flexiblen plattformübergreifenden Messaging-Funktionen (das Firebase Admin SDK basiert auf diesem Protokoll und bietet alle seine inhärenten Vorteile). Da neue Funktionen normalerweise nur der HTTP v1-API hinzugefügt werden, empfehlen wir die Verwendung dieser API für die meisten Anwendungsfälle.
  • Das Legacy- HTTP -Protokoll.
  • Das XMPP -Serverprotokoll. Beachten Sie, dass Sie XMPP verwenden müssen, wenn Sie Upstream-Messaging von Ihren Clientanwendungen verwenden möchten.

Firebase Admin SDK für FCM

Die Admin-FCM-API übernimmt die Authentifizierung beim Backend und erleichtert das Senden von Nachrichten und das Verwalten von Themenabonnements. Mit dem Firebase Admin SDK können Sie:

  • Senden Sie Nachrichten an einzelne Geräte
  • Senden Sie Nachrichten an Themen und Bedingungsanweisungen, die einem oder mehreren Themen entsprechen.
  • Abonnieren und Abbestellen von Geräten für und von Themen
  • Konstruieren Sie Nachrichtennutzlasten, die auf verschiedene Zielplattformen zugeschnitten sind

Das Admin Node.js SDK bietet Methoden zum Senden von Nachrichten an Gerätegruppen.

Informationen zum Einrichten des Firebase Admin SDK finden Sie unter Hinzufügen des Firebase Admin SDK zu Ihrem Server . Wenn Sie bereits ein Firebase-Projekt haben, beginnen Sie mit Add the SDK . Sobald das Firebase Admin SDK installiert ist, können Sie mit dem Schreiben von Logik zum Erstellen von Sendeanforderungen beginnen .

FCM-Serverprotokolle

Derzeit bietet FCM diese rohen Serverprotokolle:

Ihr App-Server kann diese Protokolle separat oder zusammen verwenden. Da es das aktuellste und flexibelste zum Senden von Nachrichten an mehrere Plattformen ist, wird die FCM HTTP v1-API empfohlen, wo immer dies möglich ist. Wenn Ihre Anforderungen Upstream-Messaging von Geräten an den Server umfassen, müssen Sie das XMPP-Protokoll implementieren.

XMPP-Messaging unterscheidet sich in folgenden Punkten vom HTTP-Messaging:

  • Upstream/Downstream-Nachrichten
    • HTTP: Nur Downstream, Cloud-zu-Gerät.
    • XMPP: Upstream und Downstream (Gerät-zu-Cloud, Cloud-zu-Gerät).
  • Messaging (synchron oder asynchron)
    • HTTP: Synchron. App-Server senden Nachrichten als HTTP-POST-Anforderungen und warten auf eine Antwort. Dieser Mechanismus ist synchron und verhindert, dass der Absender eine weitere Nachricht sendet, bis die Antwort empfangen wird.
    • XMPP: Asynchron. App-Server senden/empfangen Nachrichten an/von all ihren Geräten mit voller Leitungsgeschwindigkeit über dauerhafte XMPP-Verbindungen. Der XMPP-Verbindungsserver sendet Bestätigungs- oder Fehlerbenachrichtigungen (in Form von speziellen ACK- und NACK-JSON-codierten XMPP-Nachrichten) asynchron.
  • JSON
    • HTTP: JSON-Nachrichten, die als HTTP POST gesendet werden.
    • XMPP: JSON-Nachrichten, die in XMPP-Nachrichten eingekapselt sind.
  • Einfacher Text
    • HTTP: Nur-Text-Nachrichten, die als HTTP POST gesendet werden.
    • XMPP: Nicht unterstützt.
  • Multicast-Downstream-Senden an mehrere Registrierungstoken.
    • HTTP: Unterstützt im JSON-Nachrichtenformat.
    • XMPP: Nicht unterstützt.

Implementieren des HTTP-Serverprotokolls

Um eine Nachricht zu senden, gibt der App-Server eine POST-Anforderung mit einem HTTP-Header und einem HTTP-Text aus, die aus JSON-Schlüsselwertpaaren bestehen. Einzelheiten zu den Header- und Body-Optionen finden Sie unter Erstellen von App-Server-Sendeanforderungen

Implementieren des XMPP-Serverprotokolls

Die JSON-Nutzdaten für FCM-Nachrichten ähneln dem HTTP-Protokoll, mit folgenden Ausnahmen:

  • Es gibt keine Unterstützung für mehrere Empfänger.
  • FCM fügt das erforderliche Feld message_id hinzu. Diese ID identifiziert die Nachricht eindeutig in einer XMPP-Verbindung. Die ACK oder NACK von FCM verwendet die message_id , um eine Nachricht zu identifizieren, die von App-Servern an FCM gesendet wird. Daher ist es wichtig, dass diese message_id nicht nur eindeutig ist (pro Absender-ID ), sondern immer vorhanden ist.
  • XMPP verwendet den Serverschlüssel, um eine dauerhafte Verbindung mit FCM zu autorisieren. Weitere Informationen finden Sie unter Sendeanforderungen autorisieren .

Zusätzlich zu regulären FCM-Nachrichten werden Steuernachrichten gesendet, die durch das Feld message_type im JSON-Objekt angegeben werden. Der Wert kann entweder 'ack' oder 'nack' oder 'control' sein (siehe Formate unten). Jede FCM-Nachricht mit einem unbekannten message_type kann von Ihrem Server ignoriert werden.

Für jede Gerätenachricht, die Ihr App-Server von FCM erhält, muss er eine ACK-Nachricht senden. Es muss niemals eine NACK-Nachricht senden. Wenn Sie für eine Nachricht kein ACK senden, sendet FCM sie erneut, wenn das nächste Mal eine neue XMPP-Verbindung hergestellt wird, es sei denn, die Nachricht läuft zuerst ab.

FCM sendet auch eine ACK oder NACK für jede Server-zu-Gerät-Nachricht. Wenn Sie beides nicht erhalten, bedeutet dies, dass die TCP-Verbindung mitten im Vorgang geschlossen wurde und Ihr Server die Nachrichten erneut senden muss. Einzelheiten finden Sie unter Flusssteuerung .

Eine Liste aller Nachrichtenparameter finden Sie in der Protokollreferenz .

Anfrageformat

Nachricht mit Payload – Benachrichtigungsnachricht

Hier ist eine XMPP-Stanza für eine Benachrichtigungsnachricht:

<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>

Nachricht mit Nutzlast – Datennachricht

Hier ist eine XMPP-Stanza, die die JSON-Nachricht von einem App-Server an FCM enthält:

<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>

Antwortformat

Eine FCM-Antwort kann drei mögliche Formen haben. Die erste ist eine normale 'ack'-Nachricht. Wenn die Antwort jedoch einen Fehler enthält, kann die Nachricht zwei verschiedene Formen annehmen, die unten beschrieben werden.

ACK-Nachricht

Hier ist eine XMPP-Stanza, die die ACK/NACK-Nachricht von FCM an den App-Server enthält:

<message id="">
  <gcm xmlns="google:mobile:data">
  {
      "from":"REGID",
      "message_id":"m-1366082849205"
      "message_type":"ack"
  }
  </gcm>
</message>

NACK-Nachricht

Ein NACK-Fehler ist eine reguläre XMPP-Nachricht, in der die message_type "nack" ist. Eine NACK-Nachricht enthält:

  • Ein NACK-Fehlercode.
  • Eine NACK-Fehlerbeschreibung.

Nachfolgend finden Sie einige Beispiele.

Fehlregistrierung:

<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>

Ungültiges 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>

Gerätenachrichtenrate überschritten:

<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>

Eine vollständige Liste der NACK -Fehlercodes finden Sie in der Serverreferenz. Sofern nicht anders angegeben, sollte eine NACK-Nachricht nicht wiederholt werden. Unerwartete NACK-Fehlercodes sollten genauso behandelt werden wie INTERNAL_SERVER_ERROR .

Stanza-Fehler

In bestimmten Fällen kann es auch zu einem Zeilengruppenfehler kommen. Ein Zeilensprungfehler enthält:

  • Stanza-Fehlercode.
  • Stanza-Fehlerbeschreibung (freier Text).

Beispielsweise:

<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>

Nachrichten kontrollieren

FCM muss regelmäßig eine Verbindung schließen, um einen Lastausgleich durchzuführen. Bevor es die Verbindung schließt, sendet FCM eine CONNECTION_DRAINING Nachricht, um anzuzeigen, dass die Verbindung geleert wird und bald geschlossen wird. "Entleeren" bezieht sich auf das Abschalten des Flusses von Nachrichten, die in eine Verbindung kommen, aber das Weiterlaufenlassen dessen, was sich bereits in der Pipeline befindet. Wenn Sie eine CONNECTION_DRAINING Nachricht erhalten, sollten Sie sofort mit dem Senden von Nachrichten an eine andere FCM-Verbindung beginnen und bei Bedarf eine neue Verbindung öffnen. Sie sollten jedoch die ursprüngliche Verbindung offen halten und weiterhin Nachrichten empfangen, die über die Verbindung kommen (und sie bestätigen) – FCM behandelt das Initiieren einer Verbindung, wenn sie bereit ist.

Die Meldung CONNECTION_DRAINING sieht so aus:

<message>
  <data:gcm xmlns:data="google:mobile:data">
  {
    "message_type":"control"
    "control_type":"CONNECTION_DRAINING"
  }
  </data:gcm>
</message>

CONNECTION_DRAINING ist derzeit der einzige unterstützte control_type .

Ablaufsteuerung

Jede an FCM gesendete Nachricht erhält entweder eine ACK- oder eine NACK-Antwort. Nachrichten, die keine dieser Antworten erhalten haben, gelten als ausstehend. Wenn die Anzahl der ausstehenden Nachrichten 100 erreicht, sollte der App-Server aufhören, neue Nachrichten zu senden und darauf warten, dass FCM einige der vorhandenen ausstehenden Nachrichten bestätigt, wie in Abbildung 1 dargestellt:

Detailliertes Diagramm des Kontrollflusses zwischen FCM und dem App-Server

Abbildung 1. Nachrichten-/Bestätigungsfluss.

Um eine Überlastung des App-Servers zu vermeiden, stoppt FCM umgekehrt das Senden, wenn zu viele unbestätigte Nachrichten vorhanden sind. Daher sollte der App-Server Upstream-Nachrichten, die von der Client-Anwendung über FCM empfangen werden, so bald wie möglich "ACK"-schreiben, um einen konstanten Fluss eingehender Nachrichten aufrechtzuerhalten. Das oben genannte Limit für ausstehende Nachrichten gilt nicht für diese ACKs. Auch wenn die Anzahl der ausstehenden Nachrichten 100 erreicht, sollte der App-Server weiterhin ACKs für von FCM empfangene Nachrichten senden, um die Zustellung neuer Upstream-Nachrichten nicht zu blockieren.

ACKs sind nur im Kontext einer Verbindung gültig. Wenn die Verbindung geschlossen wird, bevor eine Nachricht bestätigt werden kann, sollte der App-Server warten, bis FCM die Upstream-Nachricht erneut sendet, bevor er sie erneut bestätigt. In ähnlicher Weise sollten alle anhängigen Nachrichten, für die kein ACK/NACK von FCM empfangen wurde, bevor die Verbindung geschlossen wurde, erneut gesendet werden.