1. 概要
この一連の Codelab(セルフペース型のハンズオン チュートリアル)は、Google App Engine(Standard)のデベロッパーが一連の移行手順をご案内し、アプリをモダナイズできるようにすることを目的としています。このような移行の大半は、元のランタイム バンドル サービスからの移行に関わるものです。次世代ランタイムは柔軟性が高く、ユーザーに幅広いサービス オプションが提供されるためです。アプリをモダナイズするもう 1 つの方法は、より新しいプロダクトにアップグレードする方法です。これについては、この Codelab のテーマです。
Cloud NDB または Cloud Datastore のクライアント ライブラリを使用して Datastore にアクセスする App Engine ユーザーは簡単に使用でき、これ以上移行する必要はありません。一方、Cloud Firestore は最新のスケーラブルで高可用性を備えた最新の NoSQL データストアであり、Firebase リアルタイム データベースの機能を利用できます。
Firestore の機能をぜひ活用したいとお考えのデベロッパーや、少なくとも移行の内容を詳しく把握したいとお考えのデベロッパーの方に最適です。このチュートリアルでは、Cloud Datastore を使用する App Engine アプリを Cloud Firestore に移行する方法について説明します。
方法を学ぶ対象
- Datastore と Firestore の違いを理解する
- Cloud Datastore から Cloud Firestore に移行する
必要なもの
- 次の対象を使用した Google Cloud Platform プロジェクト。
- 基本的な Python スキル
- 一般的な Linux コマンドに関する実践的な知識
- App Engine アプリの開発とデプロイに関する基礎知識
- このモジュール(モジュール 6)を開始する前に、モジュール 3 の Codelab(Python 3 への移植を含む)を完了することをおすすめします。
- 動作中のモジュール 3 Cloud Datastore Python 3 App Engine アプリ。
アンケート
この Codelab をどのように使用されますか?
<ph type="x-smartling-placeholder">2. 背景情報
App Engine の Datastore は 2013 年に Google Cloud Datastore という独自のサービスになりましたが、現在は App Engine 以外のデベロッパーも利用できます。翌年、Firebase は Google に買収されました。当時、同社はリアルタイム データベースで有名でした。
今後数年間にわたり、Firebase と Cloud Datastore のチームは、一部の Firebase 機能を Datastore に統合する取り組みを進めてきました。その結果、2017 年に次世代の Cloud Datastore がリリースされました。一部の Firebase 機能の継承を反映して、Cloud Firestore に名称変更されました。
Cloud Firestore は、Google Cloud プロジェクトのデフォルトの NoSQL ストレージ メカニズムになりました。新しいアプリでは Cloud Firestore をネイティブで使用できますが、既存の Datastore データベースは内部で Firestore に変換され、「Datastore モードの Firestore」として動作しています。Datastore オペレーションとの互換性を維持します。そのため、アプリケーションはいずれかのモードでのみ Cloud Firestore を動作させ、一度設定すると変更できません。
現在、ユーザーが新しいプロジェクトを作成して NoSQL ソリューションを選択すると、Datastore モードの Firestore またはネイティブ モードの Firestore のいずれかを選択するように求められます。Datastore エンティティを追加すると、ユーザーは Firestore に変更できなくなります。同様に、Firestore ネイティブ モードが選択されると、Datastore に戻すことも、Datastore モードの Firestore に戻すこともできなくなります。詳細については、ドキュメントの Cloud Firestore の Datastore モードとネイティブ Firestore モードのどちらを選択するかをご覧ください。アプリを Firestore に移行するには、新しいプロジェクトを作成し、Datastore をエクスポートしてから Firestore にインポートする必要があります。このチュートリアルの目的は、Cloud Datastore と Cloud Firestore の使用方法の違いをデベロッパーに理解してもらうことです。
この移行は、Google がユーザーによる実行を期待するものではありません。そのため、この移行は任意となっています。Cloud Firestore をネイティブで使用することには、クライアント認証、Firebase ルールの統合、そしてもちろん Firebase リアルタイム データベースなど、明らかなメリットがありますが、移行手順は「不便」です。
- 現在のアプリのプロジェクトとは異なるプロジェクトを使用する必要があります。
- アプリによって Datastore エンティティが追加されたプロジェクトは、ネイティブ モードの Firestore に切り替えられない
- 同様に、ネイティブ モードの Firestore を選択したプロジェクトで、Datastore モードの Firestore に戻すことはできません。
- プロジェクト間でデータをストリーミングできる移行ツールはありません。
- 名前空間や高い書き込みスループット(10,000 回/秒以上)など、Datastore の一部の重要な機能は Firestore では使用できません。
- エクスポート ツールとインポート ツールは「プリミティブ」「all or none」説明します。
- アプリに Datastore のエンティティが多数ある場合、エクスポートしてから Firestore にインポートするのに数時間かかることがあります。
- この期間中、アプリケーション / サービスはデータの書き込みや更新ができません。
- 移行アクティビティは通常の使用量にカウントされます。費用を最小限に抑えるために、(可能であれば 1 日の割り当て全体に)分散することをおすすめします。
- 新しいサービスは別のプロジェクトで実行されるため、DNS の更新が伝播されるまでの期間が必要になります。
- Datastore と Firestore は類似しているがデータモデルが異なるため、移行するにはアプリやサービスの動作を更新する必要があります。
- Datastore の祖先クエリは Firestore コレクション クエリ(デフォルト)になりました
- Datastore からの広範なタイプのクエリは Firestore のコレクション グループ クエリ
- インデックスや処理の違いなど
とは言え、移行が比較的簡単なアプリをお持ちで、そのような移行をシミュレートする準備をされている場合や、ここで Datastore と Firestore について学習したい場合は、続行してください。
Python 2 の場合: このオプションの移行 Codelab は Python 3 のみで提供されていますが、Cloud Firestore は 2.x もサポートしているため、使用における違いを補間できます。たとえば、Firestore レコードは(バイト文字列ではなく)Unicode 文字列を使用するため、Python 2 の文字列リテラルには u''
先頭インジケーターが必要です。つまり、2.x の store_visit()
関数は次のようになります。
def store_visit(remote_addr, user_agent):
doc_ref = fs_client.collection(u'Visit')
doc_ref.add({
u'timestamp': datetime.now(),
u'visitor': u'{}: {}'.format(remote_addr, user_agent),
})
それ以外は、クライアント ライブラリも同様に動作するはずです。考慮すべきもう 1 つの問題は、2.x の Cloud Firestore ライブラリが「フリーズ」していることです。開発が進むにつれ、今後ますます多くの新機能が使えるようになるのは、3.x Firestore クライアント ライブラリに限られます。
この移行を進めるための、このチュートリアルの主な手順は次のとおりです。
- セットアップ / 事前作業
- Cloud Firestore ライブラリを追加する
- アプリケーション ファイルの更新
3. 設定/事前作業
チュートリアルの主要部分に進む前に、まずプロジェクトをセットアップし、コードを取得してから、ベースライン アプリをデプロイします。これで、作業コードを使って作業を開始できます。
1. プロジェクトのセットアップ
モジュール 3 の Codelab で使用したプロジェクトと同じプロジェクトを再利用することをおすすめします。または、新しいプロジェクトを作成するか、別の既存のプロジェクトを再利用することもできます。プロジェクトにアクティブな請求先アカウントがあり、App Engine(アプリ)が有効になっていることを確認します。
2. ベースラインのサンプルアプリを取得する
この Codelab の前提条件の 1 つは、モジュール 3 のサンプルアプリを使用することです。お持ちでない場合は、モジュール 3 のチュートリアル(上記のリンク)を完了してから、この先に進んでください。すでにその内容に慣れている場合は、以下のモジュール 3 のコードを選択して開始できます。
使用するコードにかかわらず、モジュール 3 のコードから開始します。このモジュール 6 の Codelab では各ステップを説明します。完了すると、FINISH ポイントのコードに似ています。(このチュートリアルは Python 3 でのみ使用できます)。
- 開始: モジュール 3 リポジトリ
- 終了: モジュール 6 リポジトリ
- リポジトリ全体(ZIP のクローンを作成するかダウンロードします)
モジュール 3 ファイルのディレクトリ(ご自身または Google のもの)は次のようになります。
$ ls
README.md main.py templates
app.yaml requirements.txt
3. モジュール 3 アプリを(再)デプロイする
この段階で実施する必要がある残りの事前作業のステップ:
gcloud
コマンドライン ツールについて復習する(必要な場合)- モジュール 3 のコードを App Engine に(再)デプロイする(必要な場合)
各手順を正常に実行して、動作していることを確認したら、このチュートリアルに進み、構成ファイルを使用して作業を開始します。
Python 2 の要件
app.yaml
が(引き続き)サードパーティのバンドル パッケージ(grpcio
とsetuptools
)を参照していることを確認します。appengine_config.py
が引き続きpkg_resources
とgoogle.appengine.ext.vendor
を使用して、アプリがサードパーティのリソースを参照するようにします。requirements.txt
を更新する次のセクションでは、2.x と互換性のある最終バージョンの Python Firestore クライアント ライブラリであるgoogle-cloud-firestore==1.9.0
を使用する必要があります。requirements.txt
にgoogle-cloud-core
のエントリがある場合は、そのままにします。lib
を削除し、pip install -t lib -r requirements.txt
で再インストールします。
4. 構成ファイルを更新する(Cloud Firestore ライブラリの追加)
設定後に必要なステップは、構成を更新し、その後にアプリケーション ファイルを更新することです。前者の場合、構成変更は requirements.txt
ファイルでのマイナー パッケージのスワップのみであるため、ここで行います。
次のように、requirements.txt
の google-cloud-datastore
行を google-cloud-firestore
に置き換えます。
Flask==1.1.2
google-cloud-firestore==2.0.2
各ライブラリの最新バージョンを使用することをおすすめします。上記のバージョン番号は、このドキュメントの作成時点で最新のものです。FINISH リポジトリ フォルダ内のコードはより頻繁に更新されており、新しいバージョンが含まれている可能性があります。
その他の構成変更はないため、app.yaml
と templates/index.html
は現状のままです。
5. アプリケーション ファイルを更新する
アプリケーション ファイルは main.py
という 1 つしかないため、このセクションのすべての変更は、そのファイルにのみ影響します。
1. インポート
パッケージ インポートの切り替えは、datastore
から firestore
への軽微な変更です。
- 変更前:
from google.cloud import datastore
- 変更後:
from google.cloud import firestore
2. Firestore へのアクセス
Flask を初期化したら、Firestore クライアントを作成します。クライアントの初期化のために、上記と同様の変更を加えます。
- 変更前:
app = Flask(__name__)
ds_client = datastore.Client()
- 変更後:
app = Flask(__name__)
fs_client = firestore.Client()
Cloud NDB から Cloud Datastore への移行を実行したことで、Cloud Firestore に移行するための手間のかかる作業はすでに完了しています。Datastore では、共通のプロパティで構成されるエンティティの形式でデータレコードを作成し、キーでグループ化します。Firestore のデータレコードはドキュメントであり、Key-Value ペアで構成され、コレクションにグループ化されます。Datastore から移行する場合、これらの違いは、データレコードの作成やクエリの際に具体化されるため、考慮する必要があります。Datastore のコードの複雑さによって結果が異なる場合があります。
Datastore では、フィルタリングや並べ替えの条件とともに、エンティティ タイプに基づいたクエリを行います。Firestore の場合、データのクエリも同様です。次のクエリ値、クライアント(それぞれ ds_client
または fs_client
)、インポートについて、簡単な例を見てみましょう。
from datetime import datetime
from firestore.Query import DESCENDING
OCT1 = datetime(2020, 10, 1)
LIMIT = 10
Datastore で、2020 年 10 月 1 日以降の Visit
エンティティを降順で 10 件検索します。
query = ds_client.query(kind='Visit')
query.add_filter('timestamp', '>=', datetime(2020, 10, 1))
query.order = ['-timestamp']
return query.fetch(limit=LIMIT)
Firestore についても、Visit
コレクションから行います。
query = fs_client.collection('Visit')
query.where('timestamp', '>=', datetime(2020, 10, 1))
query.order_by('timestamp', direction=DESCENDING)
return query.limit(LIMIT).stream()
サンプルアプリのクエリはよりシンプルです(「WHERE」句がありません)。復習として、Cloud Datastore コードを次に示します。
- 変更前:
def store_visit(remote_addr, user_agent):
entity = datastore.Entity(key=ds_client.key('Visit'))
entity.update({
'timestamp': datetime.now(),
'visitor': '{}: {}'.format(remote_addr, user_agent),
})
ds_client.put(entity)
def fetch_visits(limit):
query = ds_client.query(kind='Visit')
query.order = ['-timestamp']
return query.fetch(limit=limit)
Firestore に移行すると、エンティティに類似した新しいドキュメントと、前述のクエリが作成されます。
- 変更後:
def store_visit(remote_addr, user_agent):
doc_ref = fs_client.collection('Visit')
doc_ref.add({
'timestamp': datetime.now(),
'visitor': '{}: {}'.format(remote_addr, user_agent),
})
def fetch_visits(limit):
visits_ref = fs_client.collection('Visit')
visits = (v.to_dict() for v in visits_ref.order_by('timestamp',
direction=firestore.Query.DESCENDING).limit(limit).stream())
return visits
メイン関数 root()
は、index.html
テンプレート ファイルと同じです。変更を再確認し、保存、デプロイ、検証します。
6. 概要/クリーンアップ
アプリケーションのデプロイ
gcloud app deploy
を使用してアプリを再デプロイし、アプリが動作していることを確認します。これで、コードはモジュール 6 リポジトリの内容と一致します(必要に応じて 2.x バージョンを使用します)。
先行するいずれの Codelab の取り組みも行わずにこのシリーズに進んだ場合、アプリ自体は変更されません。このアプリは、メインのウェブページ(/
)へのすべての訪問を登録します。一定回数以上サイトにアクセスすると、ウェブページは次のように表示されます。
このオプションのモジュール 6 の移行が完了しました。これはおそらく、最終版ではないにしても、App Engine のデータ ストレージに関わる移行作業の 1 つです。移行の選択肢の一つとして、まだ検討していないのであれば、Cloud Run 用にアプリをコンテナ化することもできます(モジュール 4 と 5、下記の Codelab をご覧ください)。
オプション: クリーンアップ
次の移行 Codelab に進む準備が整うまで、課金されるのを回避するためのクリーンアップを行うにはどうすればよいでしょうか。既存のデベロッパーの方は、App Engine の料金に関する情報に関する最新の内容をすでにご存じと思われます。
オプション: アプリを無効にする
次のチュートリアルに進む準備がまだ完了していない場合は、アプリを無効にすることで課金されないようにできます。次の Codelab に進む準備ができた時点で、再度有効にできます。アプリが無効になっている間は、トラフィックが発生することはありませんが、Firestore の使用量が無料の割り当てを超過した場合は、課金対象となるため、その上限に収まるように十分な量を削除します。
ただし、移行を続けず、すべてを完全に削除する場合は、プロジェクトをシャットダウンしてください。
次のステップ
このチュートリアル以外にも、移行モジュールの Codelab を利用できます。
- モジュール 7: App Engine の push タスクキュー([push] タスクキューを使用する場合に必要)
- App Engine
taskqueue
プッシュタスクをモジュール 1 アプリに追加する - モジュール 8 で Cloud Tasks に移行するユーザーの準備を行う
- App Engine
- モジュール 4: Docker を使用して Cloud Run に移行する
- Docker を使用して、Cloud Run で実行できるようにアプリをコンテナ化します。
- この移行により、引き続き Python 2 を使用できます。
- モジュール 5: Cloud Build を使用した Cloud Run への移行。
- Cloud Build を使用して Cloud Run で実行するようにアプリをコンテナ化します。
- Docker、コンテナ、
Dockerfile
についての知識は何も必要ありません。 - すでに Python 3 に移行しているアプリが必要です(Buildpacks では Python 2 はサポートされていません)。
7. 参考情報
App Engine 移行モジュールの Codelab に関する問題 / フィードバック
この Codelab に問題が見つかった場合は、提出する前にまず問題を検索してください。新しい問題の検索と登録を行うためのリンク:
移行に関するリソース
以下の表に、モジュール 3(START)とモジュール 6(FINISH)のリポジトリ フォルダへのリンクを示します。また、これらのファイルには、すべての App Engine 移行のリポジトリからアクセスすることもできます。このクローンの作成や ZIP ファイルのダウンロードも可能です。
Codelab | Python 2 | Python 3 |
(コード) | ||
モジュール 6 | 該当なし |
App Engine リソース
この特定の移行に関する追加リソースは以下のとおりです。
- Python の Cloud Datastore と Cloud Firestore のリファレンス
- Python 3 および GAE 次世代ランタイムへの移行
- 全般