見出し画像

Now in REALITY Tech #35 通信速度改善のためのprotobuf対応

どうも、サーバエンジニアのうすぎぬです。今回は通信速度改善のためのprotobuf対応についてつらつら書いて行きます。

内容としては↓の4番で紹介されている内容の結果報告になります!

同じくの品質改善プロジェクトである配信Serverのマルチリージョン化の記事もよければ読んでね

実施内容

今回のプロジェクトはWeb APIによるデータのやりとりのデータフォーマットにおいてprotobufを利用するための環境整備だったり、開発ガイドライン整備あたりが目的になります。

整備の対象範囲は iOS, Android, Unity <-> Server あたりとしました。また、REALITYのクライアントアプリでは Native <-> Unity でデータの受け渡しを行なっており、今回はここのデータフォーマットも protobuf に置き換える対応を入れます。

赤枠部のデータのやり取りのデータフォーマットをprotobuf化する

protobuf とは

protocol buffers (protobuf) は、構造化されたデータをシリアライズするための言語、またはプラットフォームに依存しないシリアライズフォーマットです。データのやり取りのために使うJSONをprotobufに置き換える、というような位置付けですね。

特長として以下が挙げられます。

  • JSON と比較しデータが軽量で高速なシリアライゼーションを実現する

  • idによるfield定義が行われ、field名の変更などはある程度柔軟に行える

  • インタフェースは共通のproto定義を参照するためマルチプラットフォーム間のインターフェース共有が効率化される

REALITYでは現在APIのデータフォーマットにJSONを採用しており、これがprotobufに置き換わると、

  • Server / Clientでの負荷軽減

  • リリース柔軟性向上

  • 通信データ容量削減

    • サービス提供者視点ではServer費用削減

    • ユーザ視点ではギガが減りづらくなる

などの恩恵があります。みんなハッピー!

めちゃくちゃ雑なprotobuf要約図

ちなみに、protobufのシリアライズ / デシリアライズのパフォーマンスについては↓の記事でJSONとの比較があり、非常に分かりやすかったです。

環境

マルチプラットフォームでprotocのバージョンによるbuild差分が出ないように環境を整える必要があります。

今回は各platformで以下の環境に整備しました。

  • Server (Golang): protoc v3.17.3

  • Unity (C#): protoc v3.17.3

  • iOS (Swift): swift-protobuf

  • Android (Kotlin): protobuf-javalite

特にUnityではprotobufを利用するのが今回初めてと言うわけではなく、配信中のモーションデータのやり取りなどにprotobufを利用しています。以前は protoc 3.10.0 を使用しており、Unityのみoptional構文が使えない問題が発生し、ここでprotocのバージョン上げ対応を行いました(※proto3でoptionalが利用可能になったのはv3.12から)。

CI/CD

各環境を整える以外にもprotoc-gen-docによるAPI仕様書のドキュメンテーション自動化なども行っています。proto定義が更新されるたびに自動でprotoc-gen-docが走り、API仕様書が更新される仕組みです。

また、GitHub上で更新されたproto定義が各プラットフォームの環境で問題なくbuild可能かチェックするテストを導入しました。今後はproto定義に変更があったタイミングで各プラットフォームのリポジトリにPRを自動生成するところまで考えています。

開発フロー

余談に近いのですが、この章ではBackends For Frontends(BFF)の話を書きます。

BFFはアーキテクチャ設計パターンの1つです。フロントエンドのリクエストに応じて各種のAPIコールをしたり、バックエンドから取得した内容を加工してフロントエンドに返却したりするフロントエンド専用のサーバーを用意するアーキテクチャ設計パターンです。

https://techblog.zozo.com/entry/zozo-aggregation-api-bff

REALITYのServerはマイクロサービス構成になっていますが、実施内容章のAPI環境の図の通り、Gateway Appが設置されクライアントがコールするAPIは全てGateway Appに集約されています。

まあ、このサーバアーキテクチャそのものがBFFと言えるのですが、今回はそこからさらに踏み込み、開発フローにもBFFの思想を取り入れることにしました。具体的には以下の点を実現すべく、API interface(proto定義)はクライアントエンジニアが定義するように開発ガイドラインを設計しました。(※ただしサーバエンジニアによる設計相談/レビューを必須とする)

  • レスポンス中のクライアント処理に不要なパラメータの排除

  • 1 screen 1 api call によるAPI設計

    • クライアントの画面名とAPIのpathを合わせる

美しいAPI設計を目指して行きたいですね。

効果計測

今回は、REALITYのWeb APIの中でも特に総通信データ量が多い

  • 配信ステータス取得API

  • ギフト一覧取得API

のprotobuf化を行いました。

下図はギフト一覧取得APIについて、JSONで扱った時とprotobufで扱った時のクライアント視点でのレスポンスペイロードのサイズ比較の図になります。図の数値を見て取れるように約60%のサイズカットを実現しました。JSONでやりとりしていた頃もgzipなど利用し容量削減には努めていたので想像以上の効果でした。

(左)JSONでのinterface定義でのレスポンスペイロードサイズ
(右)protobuf移行後のレスポンスペイロードサイズ

さらに、 iOS, Android, Unity, Server すべてにおいてデータのparseにかけるリソースも減っているのでみんなハッピーです。

最後に

今回のプロジェクトではマルチプラットフォームでのprotobufによるデータ交換を実現しました。
これからも、REALITYでは本プロジェクトのように積極的にパフォーマンス改善や開発フロー改善を行なっていきます。そんなREALITYでは最高のサービスを一緒に作ってくれるエンジニアを募集しています!

気になった方は是非カジュアル面談からでもどうでしょうか