2021/01/05

Health Planet と Fitbit 連携 Web サービス開発日記 : 全体アーキテクチャの紹介

 hp2fit.app のアーキテクチャを備忘録として紹介。

特徴はすべて Google Cloud Platform 上で動かしていて、以下の製品を組み合わせています。

バックエンドで動く Cloud Run と Cloud Functions 上のアプリケーションの開発言語は golang です。

以下が全体概要図です。


UI とバックエンド

Web アプリなので、Web フロントエンドとしては Firebase Hosting を使って、HTML や JavaScript などの静的コンテンツをホスティングしています。画面上に表示するデータに関しては、JavaScript でFirebase の Realtime DB と同じように Firestore のデータを動的に表示しています。

Oauth 処理

ユーザー操作として行う HealthPlanet と Fitbit の Oauth トークン登録に関しては、redirect されて渡される code を受け取りアクセストークンに変換する処理が必要なので、バックエンドとの連携のため、Firebase Hosting の rewrite 機能を利用して Cloud Run を呼び出しています。

この redirect を受ける Cloud Run では、各 API サービスから受け取った code を Firestore に保存するまでしか実施していません。code から access token に変換する処理に関しては Firestore のドキュメントへの書き込みをトリガーとして動く、Cloud Functions で処理するようにしています。これは、UI として極力バックエンド側の処理の間の待ち時間を作らないようにするためです。

データ連携の非同期処理

access token が登録されると、あとは Cloud Scheduler で自動的に毎時のバッチ処理を呼び出し、 Health Planet からデータを取得し、体重と体脂肪のデータを Fitbit に登録します。ここでの処理は基本的にすべて非同期処理にしています。

Cloud Run は Cloud Functions に比べて比較的長めの処理ができますが、それでもデータ量によって処理時間の変動が大きい場合には非同期処理にしたいです。とくに今回の Web アプリは基本的に勝手に動くバッチ処理なので、タスクごとに非同期処理にすることと並列処理にして処理を分散させようにしておくと、万が一にユーザー数が急伸しても対応できるようになります。

非同期で並列処理とするため今回は Cloud Tasks を利用しています。各ユーザーの Health Planet からのデータ取得、Fitbit へのデータの登録、古いデータの削除、などの処理はすべて Cloud Tasks を介して処理を起動させています。呼び出し側は最低限の処理だけの実行時間で済むため、処理待ちの時間を気にする必要がありません。特に、他サービスとの連携処理、こ会の場合だと Health Planet API でデータを取得する部分や fitbit API にデータを Post する部分は、他サービスの呼び出し時間や処理時間に依存するため、内部の処理に比べて待ち時間が長くなります。さらにそれをループ処理などで繰り返し呼び出しになると、繰り返し回数によって大幅に処理時間が変動しますので、こういった処理は非同期処理にして並列化しておきます。

もちろん、他サービス側の呼び出しの Quota に引っかかる場合もあるので、ここは Cloud Tasks のキューの流量で調整し対応することができます。

Cloud Run の認証

Cloud Run は、Firebase Hosting の rewrite で呼び出されるもの以外は、すべて呼び出しに認証が必要で、GCP のプロジェクトの中の特定の Service Account からしか実行できないようにしています。

UI から呼び出されて rewrite で呼び出される Cloud Run は、未承認で実行できるようにしていますが、その処理が Firebase Authentication で認証されたユーザーであるかどうかを Authentication Bearer ヘッダーを使って処理の最初に確認しています。Oauth 承認処理の中でもこの Bearer を受け渡すことで認証されたユーザーを確認しています。





0 件のコメント:

コメントを投稿