FCM HTTP v1 API 移行における注意点

Firebase Cloud Messaging を利用してアプリケーションにプッシュ通知を送っている方は既にご存知かと思いますが、 2024年6月20日をもって Firebase Cloud Messaging(FCM)レガシーレジスタAPIとレガシー送信APIの数が削減されます。いくつかのAPIの廃止により、すでに廃止されたSDKや機能の一部は6月20日以降に動作しなくなるため、新しいAPIやそれに対応したSDKのメソッドに置き換えることが必要です。 詳細は2023年6月21日に "[Action Required] Update your apps to the latest Firebase Cloud Messaging APIs and SDKs" と題したメールが届いているはずなので、Deprecation の詳細と影響のあるプロジェクトをご自身で確認することをお勧めします。

Batch API Deprecation

今回の Legacy HTTP ProtocolFirebase Admin SDK Batch Send API ( sendMulticast() メソッド含む) の廃止により、Legacy API に頼らずに多くのデバイスに大規模かつ低レイテンシでマルチキャストメッセージを同時に送信することが難しくなりました。ガイドに沿って新しいAPIへ移行するだけだと、以前のパフォーマンスを維持したまま送信することができないので注意が必要という話をします。

Batch API とは何か

バッチ送信と呼ばれるFCMへの単一のHTTPリクエストに複数の送信リクエストを含めることができるAPIです。Admin SDK 経由で送信している場合、以下のメソッドが Batch API を利用しています。

  • sendAll()
  • sendMulticast()
    • 内部で sendAll() を使っています

FCM HTTP v1 API ベースの移行先メソッドは以下の通りです。利用中の各言語の Admin SDK のドキュメントコメントを確認してください。

  • sendAll()sendEach()
  • sendMulticast()sendEachMulticast()

Batch API を使うと一度のHTTPリクエストで500トークンに対して送信することができるため、低レイテンシで多くのトークンにメッセージを送ることが可能でした。多くのトークンに対してメッセージを送信する場合、トピックにメッセージを送信することも有効ですが、1つのアプリがサブスクライブできるトピック数は 2,000 トピックまでとなっており、複雑なメッセージ制御が必要なケースや、異なるメッセージを同時に送信したい場合などにこの Batch API が有用でした。

なぜ注意が必要なのか

Admin SDK を利用して移行する場合、 素直に sendEachsendEachMulticast に書き換えるだけでは Batch API 同等のパフォーマンスを発揮することはできません。 新しい FCM HTTP v1 API はリクエストごとに1つのトークンしか受け付けないため、基本的にはメッセージのトークンごとにHTTPリクエスト全体を送信する必要があります。大規模での多数のトークンへの送信は、HTTP 1.0 / 1.1で非常に遅くなる可能性があり、多くのTCP接続が必要になります。現在確認できるかぎり、Node.js の公式 Firebase Admin SDK ではこの sendEach メソッドにおいて単一のトークンごとに新しいHTTP 1.0接続を同時に開くため安易に移行するのはオススメできないという状況です...。

ではどうするのか

幸い FCM HTTP v1 API は HTTP/2 for Multiplexing に対応しています(!)。Multiplexingでは1つのHTTPコネクションの中に複数のストリーム (チャネルみたいなもの) を立てることにより、複数のHTTPリエクエストを同時に送信することができます。HTTP/2ベースで v1 API を直接利用するように実装する必要はありますが、現状の Batch API 同等かそれ以上のパフォーマンスを求める場合はこの方法しかないでしょう。

以下のFAQ*1にもこのことは記載されており、100トークン未満ならHTTP/2上のHTTP v1 APIは、マルチキャスト要求の99.9%に対して同様に機能するとのことです。(そこは500トークンであってほしかった...)

Q: Does the HTTP v1 API support sending messages to multiple tokens in one request?

A: No. This feature, called "multicast" in legacy HTTP APIs, is not supported by the HTTP v1 API, which is better designed for scalability.\n

For use cases where end-to-end latency is critical, or where total fanout size is small (fewer than 1 million), Google recommends sending multiple separate requests using the HTTP v1 API. The HTTP v1 API over HTTP/2 performs similarly for 99.9% of multicast requests (sending < 100 tokens). For outlier use cases (sending 1000 tokens), it achieves up to a third of the throughput rate, so additional concurrency is needed to optimize for this atypical use case. Users can experience more reliability and availability with the HTTP v1 API than with legacy multicast.

firebase.google.com


公式の Admin SDK が HTTP/2 for Multiplexing に対応するかは現時点では不明ですが、今の所特に動きはありません。 自分はまだ移行を完了していないので、引き続きこのトピックは注視していきたいと思いますが、6月21日の Batch API の廃止の影響を最小限に留めるためには HTTP/2 ベースで実装するしかなさそうですね、というお話でした。

*1:FAQのFCM features deprecated in June 2023の章は日本語ではまだ表示されません。Englishで確認しましょう。