1. 概要
サーバーレス移行ステーション シリーズの Codelab(ご自分のペースで進められる実践型のチュートリアル)と関連動画は、主にレガシー サービスからの移行を 1 つ以上行うことで、Google Cloud サーバーレスのデベロッパーがアプリケーションをモダナイズできるよう支援することを目的としています。これにより、アプリの移植性が向上し、オプションと柔軟性が高まるため、幅広い Cloud プロダクトとの統合やアクセスが可能になり、新しい言語リリースへのアップグレードが容易になります。このシリーズは、当初は初期の Cloud ユーザー、主に App Engine(標準環境)のデベロッパーを対象としていましたが、Cloud Functions や Cloud Run などの他のサーバーレス プラットフォームや、該当する場合は他のプラットフォームも対象とするほど幅広くなっています。
この Codelab の目的は、Python 2 App Engine デベロッパーが App Engine Memcache から Cloud Memorystore(Redis 用)に移行する方法を示すことです。App Engine ndb から Cloud NDB への暗黙的な移行もありますが、これは主にモジュール 2 の Codelab で説明しています。詳細な手順については、こちらをご覧ください。
GCP コンソールの
- Cloud Memorystore インスタンスを設定する(Cloud コンソールまたは
gcloudツールから) - Cloud サーバーレス VPC アクセス コネクタを設定する(Cloud Console または
gcloudツールを使用) - App Engine Memcache から Cloud Memorystore に移行する
- サンプルアプリで Cloud Memorystore を使用してキャッシュ保存を実装する
- App Engine
ndbから Cloud NDB への移行
必要なもの
- 有効な請求先アカウントを持つ Google Cloud プロジェクト(無料の Codelab ではありません)
- 基本的な Python スキル
- 一般的な Linux コマンドに関する実践的な知識
- App Engine アプリの開発とデプロイに関する基礎知識
- 正常に機能するモジュール 12 App Engine アプリ(モジュール 12 Codelab [推奨] を完了するか、リポジトリからモジュール 12 アプリをコピーする)
アンケート
このチュートリアルの利用方法をお選びください。
Python のご利用経験はどの程度ありますか?
Google Cloud サービスの使用経験はどの程度ありますか?
2. 背景情報
この Codelab では、サンプルアプリを App Engine Memcache(および NDB)から Cloud Memorystore(および Cloud NDB)に移行する方法について説明します。このプロセスでは、App Engine バンドル サービスへの依存関係を置き換えて、アプリの移植性を高めます。App Engine を使い続けるか、前述の代替案への移行を検討できます。
この移行は、このシリーズの他の移行よりも多くの労力を必要とします。App Engine Memcache の推奨代替サービスは、フルマネージド型のクラウドベースのキャッシュ サービスである Cloud Memorystore です。Memorystore は、一般的なオープンソース キャッシュ エンジンである Redis と Memcached をサポートしています。この移行モジュールは、Cloud Memorystore for Redis を使用します。詳細については、Memorystore と Redis の概要をご覧ください。
Memorystore には実行中のサーバーが必要なため、Cloud VPC も必要です。具体的には、App Engine アプリがプライベート IP アドレスを介して Memorystore インスタンスに接続できるように、サーバーレス VPC アクセス コネクタを作成する必要があります。この演習を完了すると、アプリの動作は以前と変わりませんが、Cloud Memorystore がキャッシュ サービスになり、App Engine の Memcache サービスが置き換えられます。
このチュートリアルは、Python 2 のモジュール 12 サンプルアプリから始まり、Python 3 への追加のマイナー アップグレード(オプション)が続きます。Python 3 App Engine SDK を介して Python 3 から App Engine バンドル サービスにアクセスする方法をすでに理解している場合は、代わりに Python 3 版のモジュール 12 サンプルアプリから始めることができます。これを行うには、Memorystore は App Engine バンドル サービスではないため、SDK の使用を削除する必要があります。Python 3 App Engine SDK の使用方法については、このチュートリアルの範囲外です。
このチュートリアルでは、次の主な手順について説明します。
- セットアップ/事前作業
- キャッシュ サービスを設定する
- 設定ファイルを更新する
- メイン アプリケーションを更新する
3. セットアップ/事前作業
Cloud プロジェクトを準備する
モジュール 12 Codelab で使用したプロジェクトと同じプロジェクトを再利用することをおすすめします。または、新しいプロジェクトを作成するか、別の既存のプロジェクトを再利用することもできます。このシリーズの各 Codelab には、「START」(開始用のベースライン コード)と「FINISH」(移行後のアプリ)があります。問題が発生した場合に、ご自身のソリューションと Google のソリューションを比較できるように、FINISH コードが提供されています。何か問題が発生した場合は、いつでも START にロールバックできます。これらのチェックポイントは、移行の実行方法を確実に習得できるように設計されています。
使用する Cloud プロジェクトには、有効な請求先アカウントがあることを確認してください。また、App Engine が有効になっていることを確認してください。これらのチュートリアルを行う際の一般的な費用の影響を確認し、理解しておいてください。ただし、このシリーズの他の Codelab とは異なり、この Codelab では無料枠のない Cloud リソースを使用するため、演習を完了するには費用が発生します。より具体的な費用情報と、使用量を削減するための推奨事項が提供されます。最後に、請求額を最小限に抑えるためにリソースを解放する手順も記載されています。
ベースライン サンプルアプリを入手する
この Codelab では、ベースラインのモジュール 12 のコードから移行を段階的に進めていきます。完了すると、FINISH フォルダのいずれかのコードに酷似した、動作するモジュール 13 アプリが完成します。リソースは次のとおりです。
- 開始: モジュール 12 Python 2(
mod12)または Python 3(mod12b)アプリ - 終了: モジュール 13 Python 2(
mod13a)または Python 3(mod13b)アプリ - 移行リポジトリ全体(クローン作成または ZIP をダウンロード)
START フォルダには次のファイルが含まれている必要があります。
$ ls README.md app.yaml main.py requirements.txt templates
Python 2 バージョンから始める場合は、appengine_config.py ファイルもあります。モジュール 12 の Codelab を完了している場合は、lib フォルダもある可能性があります。
モジュール 12 アプリを(再)デプロイする
残りの事前作業のステップ:
gcloudコマンドライン ツールについて復習する(必要な場合)- モジュール 12 コードを App Engine に(再)デプロイします(必要な場合)。
Python 2 ユーザーは、次のコマンドを使用して lib フォルダを削除して再インストールする必要があります。
rm -rf ./lib; pip install -t lib -r requirements.txt
これで、すべてのユーザー(Python 2 と 3 のユーザー)が次のコマンドを使用してコードを App Engine にアップロードできるようになりました。
gcloud app deploy
デプロイが完了したら、アプリの見た目と機能がモジュール 12 のアプリ(訪問を追跡し、同じユーザーに対して 1 時間キャッシュに保存するウェブアプリ)と同じであることを確認します。

最近のアクセスはキャッシュに保存されているため、ページの更新は比較的速く読み込まれます。
4. キャッシュ サービスを設定する
Cloud Memorystore はサーバーレスではありません。インスタンスが必要です。この場合は Redis を実行しているインスタンスです。Memcache とは異なり、Memorystore はスタンドアロンの Cloud プロダクトであり、無料枠がありません。続行する前に、Memorystore for Redis の料金情報を必ずご確認ください。この演習の費用を最小限に抑えるため、運用に必要な最小限のリソース(ベーシック サービスティアと 1 GB の容量)をおすすめします。
Memorystore インスタンスは App Engine アプリ(インスタンス)とは異なるネットワークにあるため、App Engine が Memorystore リソースにアクセスできるように、サーバーレス VPC アクセス コネクタを作成する必要があります。VPC の費用を最小限に抑えるには、インスタンス タイプ(f1-micro)と、リクエストするインスタンスの最小数(最小 2 個、最大 3 個を推奨)を選択します。VPC の料金情報ページもご覧ください。
必要なリソースの作成手順を説明する際に、費用の削減に関する推奨事項を繰り返し説明します。また、Cloud コンソールで Memorystore と VPC リソースを作成すると、各プロダクトの料金計算ツールが右上隅に表示され、月額費用の見積もりを確認できます(下の図を参照)。オプションを変更すると、これらの値は自動的に調整されます。次のような結果が表示されます。

どちらのリソースも必須です。どちらを先に作成してもかまいません。Memorystore インスタンスを先に作成した場合、VPC コネクタがないと App Engine アプリからインスタンスにアクセスできません。同様に、最初に VPC コネクタを作成した場合、App Engine アプリが通信する VPC ネットワークには何もありません。このチュートリアルでは、まず Memorystore インスタンスを作成してから、VPC コネクタを作成します。
両方のリソースがオンラインになったら、関連情報を app.yaml に追加して、アプリがキャッシュにアクセスできるようにします。公式ドキュメントの Python 2 または Python 3 のガイドも参照してください。Cloud NDB 移行ページのデータ キャッシュ保存ガイド(Python 2 または Python 3)も参考になります。
Cloud Memorystore インスタンスを作成する
Cloud Memorystore には無料枠がないため、Codelab を完了するために必要な最小限のリソースを割り当てることをおすすめします。次の設定を使用すると、費用を最小限に抑えることができます。
- 最も低いサービスティアである [Basic] を選択します(コンソールのデフォルト: [Standard]、
gcloudのデフォルト: [Basic])。 - 最小のストレージ容量(1 GB)を選択します(コンソールのデフォルト: 16 GB、
gcloudのデフォルト: 1 GB)。 - 通常、どのソフトウェアでも最新バージョンは最も多くのリソースを必要としますが、古いバージョンを選択することもおすすめできません。現在、2 番目に新しいバージョンは Redis バージョン 5.0 です(コンソールのデフォルト: 6.x)。
次のセクションでは、これらの設定を念頭に置いて、Cloud Console からインスタンスを作成する手順について説明します。コマンドラインから実行する場合は、次のセクションに進んでください。
Cloud Console から
Cloud Console で Cloud Memorystore ページに移動します(お支払い情報の入力を求められることがあります)。Memorystore をまだ有効にしていない場合は、有効にするように求められます。

有効にすると(場合によっては課金も)、Memorystore ダッシュボードが表示されます。ここでは、プロジェクトで作成されたすべてのインスタンスを確認できます。下のプロジェクトには行がないため、「表示する行がありません」と表示されています。Memorystore インスタンスを作成するには、上部の [インスタンスを作成] をクリックします。

このページには、Memorystore インスタンスを作成するために必要な設定を入力するフォームがあります。

このチュートリアルとそのサンプルアプリの費用を抑えるには、前述の推奨事項に従ってください。選択が完了したら、[作成] をクリックします。作成プロセスには数分かかります。完了したら、インスタンスの IP アドレスとポート番号をコピーして app.yaml に追加します。
コマンドラインから
Cloud Console から Memorystore インスタンスを作成すると、視覚的にわかりやすいですが、コマンドラインを好むユーザーもいます。先に進む前に、gcloud がインストールされ、初期化されていることを確認してください。
Cloud Console と同様に、Cloud Memorystore for Redis を有効にする必要があります。次の例のように、gcloud services enable redis.googleapis.com コマンドを発行し、完了するまで待ちます。
$ gcloud services enable redis.googleapis.com Operation "operations/acat.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.
サービスがすでに有効になっている場合、コマンドを(再度)実行しても(負の)副作用はありません。サービスが有効になったので、Memorystore インスタンスを作成しましょう。コマンドは次のようになります。
gcloud redis instances create NAME --redis-version VERSION \
--region REGION --project PROJECT_ID
Memorystore インスタンスの名前を選択します。このラボでは、「demo-ms」という名前と「my-project」というプロジェクト ID を使用します。このサンプルアプリのリージョンは us-central1(us-central と同じ)ですが、レイテンシが気になる場合は、より近いリージョンを使用できます。App Engine アプリと同じリージョンを選択する必要があります。任意の Redis バージョンを選択できますが、ここでは前述のとおり推奨のバージョン 5 を使用します。これらの設定を指定して発行するコマンドと、関連する出力は次のようになります。
$ gcloud redis instances create demo-ms --region us-central1 \
--redis-version redis_5_0 --project my-project
Create request issued for: [demo-ms]
Waiting for operation [projects/my-project/locations/us-central1/operations/operation-xxxx] to complete...done.
Created instance [demo-ms].
Cloud コンソールのデフォルトとは異なり、gcloud は最小限のリソースにデフォルト設定されます。その結果、このコマンドではサービスティアもストレージ容量も必要ありませんでした。Memorystore インスタンスの作成には数分かかります。完了したら、インスタンスの IP アドレスとポート番号をメモします。これらはすぐに app.yaml に追加されます。
インスタンスが作成されたことを確認する
Cloud コンソールまたはコマンドラインから
Cloud Console またはコマンドラインからインスタンスを作成した場合は、次のコマンドを使用して、インスタンスが使用可能で、使用準備が整っていることを確認できます。gcloud redis instances list --region REGION
リージョン us-central1 のインスタンスを確認するコマンドと、作成したインスタンスを示す出力例を次に示します。
$ gcloud redis instances list --region us-central1 INSTANCE_NAME VERSION REGION TIER SIZE_GB HOST PORT NETWORK RESERVED_IP STATUS CREATE_TIME demo-ms REDIS_5_0 us-central1 BASIC 1 10.aa.bb.cc 6379 default 10.aa.bb.dd/29 READY 2022-01-28T09:24:45
インスタンス情報の入力やアプリの構成を求められたら、必ず HOST と PORT を使用してください(RESERVED_IP は使用しないでください)。Cloud Console の Cloud Memorystore ダッシュボードに、このインスタンスが表示されるようになります。

Compute Engine 仮想マシンから
Compute Engine 仮想マシン(VM)がある場合は、VM から Memorystore インスタンスに直接コマンドを送信して、動作を確認することもできます。VM の使用には、すでに使用しているリソースとは別に費用が発生する場合があります。
サーバーレス VPC アクセス コネクタを作成する
Cloud Memorystore と同様に、サーバーレス Cloud VPC コネクタは Cloud コンソールまたはコマンドラインで作成できます。同様に、Cloud VPC には無料枠がないため、費用を最小限に抑えるために、この設定でコードラボを完了するのに必要な最小限のリソースを割り当てることをおすすめします。
- インスタンスの最大数を最小の 3 に選択します(コンソールと
gcloudのデフォルト: 10)。 - 最もコストの低いマシンタイプを選択します。
f1-micro(コンソールのデフォルト:e2-micro、gcloudのデフォルトなし)
次のセクションでは、上記の Cloud VPC 設定を使用して Cloud Console からコネクタを作成する手順について説明します。コマンドラインから実行する場合は、次のセクションに進みます。
Cloud コンソールから
Cloud Console の [Cloud Networking] の [Serverless VPC access] ページに移動します(請求情報の入力を求められることがあります)。API をまだ有効にしていない場合は、有効にするように求めるメッセージが表示されます。

API を有効にすると(課金も有効にしている場合はそれも含む)、作成されたすべての VPC コネクタが表示されるダッシュボードが表示されます。下のスクリーンショットで使用されているプロジェクトには行がないため、「No rows to display」と表示されています。コンソールの上部にある [コネクタを作成] をクリックします。

フォームに希望の設定を入力します。

独自のアプリケーションに適した設定を選択します。このチュートリアルと最小限のニーズを満たすサンプルアプリでは、コストを最小限に抑えることが理にかなっているので、前述の推奨事項に従ってください。選択が完了したら、[作成] をクリックします。VPC コネクタの要求が完了するまでに数分かかります。
コマンドラインから
VPC コネクタを作成する前に、まず Serverless VPC Access API を有効にします。次のコマンドを発行すると、同様の出力が表示されます。
$ gcloud services enable vpcaccess.googleapis.com Operation "operations/acf.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.
API が有効になっている場合、次のようなコマンドで VPC コネクタが作成されます。
gcloud compute networks vpc-access connectors create CONNECTOR_NAME \
--range 10.8.0.0/28 --region REGION --project PROJECT_ID
コネクタの名前と、未使用の /28 CIDR ブロックの開始 IP アドレスを選択します。このチュートリアルでは、次のことを前提としています。
- プロジェクト ID:
my-project - VPC コネクタ名:
demo-vpc - 最小インスタンス数: 2(デフォルト)、最大インスタンス数: 3
- インスタンス タイプ:
f1-micro - リージョン:
us-central1 - IPv4 CIDR ブロック:
10.8.0.0/28(Cloud コンソールで推奨)
上記の前提条件を踏まえて次のコマンドを実行すると、次のような出力が表示されます。
$ gcloud compute networks vpc-access connectors create demo-vpc \
--max-instances 3 --range 10.8.0.0/28 --machine-type f1-micro \
--region us-central1 --project my-project
Create request issued for: [demo-vpc]
Waiting for operation [projects/my-project/locations/us-central1/operations/xxx] to complete...done.
Created connector [demo-vpc].
上記のコマンドでは、最小インスタンス数 2 や default という名前のネットワークなどのデフォルト値の指定が省略されています。VPC コネクタの作成が完了するまでに数分かかります。
コネクタが作成されたことを確認する
プロセスが完了したら、リージョン us-central1 であることを前提として、次の gcloud コマンドを発行し、作成されて使用できる状態になっていることを確認します。
$ gcloud compute networks vpc-access connectors list --region us-central1 CONNECTOR_ID REGION NETWORK IP_CIDR_RANGE SUBNET SUBNET_PROJECT MIN_THROUGHPUT MAX_THROUGHPUT STATE demo-vpc us-central1 default 10.8.0.0/28 200 300 READY
同様に、ダッシュボードには作成したコネクタが表示されます。

Cloud プロジェクト ID、VPC コネクタ名、リージョンをメモします。
コマンドラインまたはコンソールで必要な追加の Cloud リソースを作成したので、それらの使用をサポートするようにアプリケーション構成を更新します。
5. 構成ファイルを更新する
最初の手順は、構成ファイルに必要な更新をすべて行うことです。この Codelab の主な目的は、Python 2 ユーザーの移行を支援することですが、通常、以下の各セクションで Python 3 への移行に関する情報が提供されます。
requirements.txt
このセクションでは、Cloud Memorystore と Cloud NDB をサポートするパッケージを追加します。Cloud Memorystore for Redis の場合、Cloud Memorystore クライアント ライブラリ自体が存在しないため、標準の Redis クライアント for Python(redis)を使用するだけで十分です。redis と google-cloud-ndb の両方を requirements.txt に追加し、モジュール 12 の flask を結合します。
flask
redis
google-cloud-ndb
この requirements.txt ファイルにはバージョン番号が含まれていないため、最新バージョンが選択されます。互換性の問題が発生した場合は、バージョン番号を指定して動作するバージョンをロックします。
app.yaml
追加する新しいセクション
Python 2 App Engine ランタイムで Cloud NDB などの Cloud API を使用する場合は、grpcio と setuptools という特定のサードパーティ パッケージが必要です。Python 2 ユーザーは、app.yaml で、これらの組み込みライブラリと利用可能なバージョンをリストする必要があります。libraries セクションがまだない場合は、作成して、次のように両方のライブラリを追加します。
libraries:
- name: grpcio
version: latest
- name: setuptools
version: latest
アプリを移行する場合、すでに libraries セクションが存在している可能性があります。その場合は、grpcio と setuptools のいずれかが欠落している場合は、既存の libraries セクションに追加してください。
次に、サンプルアプリには Cloud Memorystore インスタンスと VPC コネクタの情報が必要になるため、使用している Python ランタイムに関係なく、app.yaml に次の 2 つの新しいセクションを追加します。
env_variables:
REDIS_HOST: 'YOUR_REDIS_HOST'
REDIS_PORT: 'YOUR_REDIS_PORT'
vpc_access_connector:
name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR
必要な更新は以上です。更新された app.yaml は次のようになります。
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: grpcio
version: 1.0.0
- name: setuptools
version: 36.6.0
env_variables:
REDIS_HOST: 'YOUR_REDIS_HOST'
REDIS_PORT: 'YOUR_REDIS_PORT'
vpc_access_connector:
name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR
以下は、app.yaml に適用する必要がある更新を示す「更新前と更新後」の例です。

*Python 3 の違い
このセクションは省略可能で、Python 3 に移植する場合にのみ必要です。そのためには、Python 2 の構成にいくつかの変更を加える必要があります。現時点でアップグレードしない場合は、このセクションをスキップしてください。
Python 3 ランタイムでは threadsafe も api_version も使用されないため、これらの設定を両方削除します。最新の App Engine ランタイムでは、組み込みのサードパーティ ライブラリと組み込みでないライブラリのコピーがサポートされていません。サードパーティ パッケージの要件は、requirements.txt に記載することのみです。その結果、app.yaml の libraries セクション全体を削除できます。
次に、Python 3 ランタイムでは独自のルーティングを行うウェブ フレームワークを使用する必要があるため、モジュール 1 で webapp2 から Flask に移行する方法を紹介しました。そのため、すべてのスクリプト ハンドラを auto に変更する必要があります。このアプリは静的ファイルを提供しないため、ハンドラをリストに含めるのは「無意味」です(すべて auto であるため)。したがって、handlers セクション全体を削除することもできます。その結果、Python 3 用に調整された新しい短縮形の app.yaml は次のように短縮されます。
runtime: python39
env_variables:
REDIS_HOST: 'YOUR_REDIS_HOST'
REDIS_PORT: 'YOUR_REDIS_PORT'
vpc_access_connector:
name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR
Python 3 に移植する際の app.yaml の違いをまとめると、次のようになります。
threadsafeとapi_versionの設定を削除するlibrariesセクションを削除handlersセクションを削除します(アプリが静的ファイルを提供している場合はscriptハンドラのみを削除します)。
値を置き換える
Memorystore と VPC コネクタの新しいセクションの値はプレースホルダです。大文字の値(YOUR_REDIS_HOST, YOUR_REDIS_PORT, PROJECT_ID, REGION, CONNECTOR_NAME)は、これらのリソースを以前に作成したときに保存した値に置き換えます。Memorystore インスタンスについては、RESERVED_IP ではなく HOST と PORT を使用してください。インスタンス名が demo-ms で、REGION が us-central1 であると仮定して、HOST と PORT を取得するコマンドラインの簡単な方法を次に示します。
$ gcloud redis instances describe demo-ms --region us-central1 \
--format "value(host,port)"
10.251.161.51 6379
たとえば、Redis インスタンスの IP アドレスが 10.10.10.10 で、ポート 6379 を使用し、リージョン us-central1 にあるプロジェクト my-project で VPC コネクタ名が demo-vpc の場合、app.yaml のこれらのセクションは次のようになります。
env_variables:
REDIS_HOST: '10.10.10.10'
REDIS_PORT: '6379'
vpc_access_connector:
name: projects/my-project/locations/us-central1/connectors/demo-vpc
appengine_config.py を作成または更新する
組み込みサードパーティ ライブラリのサポートを追加
先ほど app.yaml で行ったように、grpcio ライブラリと setuptools ライブラリの使用を追加します。組み込みのサードパーティ ライブラリをサポートするように appengine_config.py を変更します。この手順は、モジュール 2 で App Engine ndb から Cloud NDB に移行したときにも必要でした。必要な変更は、lib フォルダを setuptools.pkg_resources ワーキング セットに追加することです。

*Python 3 の違い
このセクションは省略可能で、Python 3 に移植する場合にのみ必要です。App Engine 第 2 世代の変更点の 1 つは、app.yaml で(組み込みでない)サードパーティ パッケージのコピー(「ベンダーリング」と呼ばれることもあります)と組み込みのサードパーティ パッケージの参照が不要になったことです。つまり、appengine_config.py ファイル全体を削除できます。
6. アプリケーション ファイルを更新する
アプリケーション ファイルは main.py の 1 つだけなので、このセクションの変更はすべてそのファイルにのみ影響します。このアプリケーションを Cloud Memorystore に移行するために行う変更を図で示します。これは説明のみを目的としており、詳細な分析を意図したものではありません。すべての作業は、コードの変更で行います。

上から順に、各セクションを 1 つずつ見ていきましょう。
インポートを更新する
モジュール 12 の main.py のインポート セクションでは、Cloud NDB と Cloud Tasks を使用しています。インポートは次のとおりです。
変更前:
from flask import Flask, render_template, request
from google.appengine.api import memcache
from google.appengine.ext import ndb
Memorystore に切り替えるには環境変数を読み取る必要があります。つまり、Python Redis クライアントである redis と Python os モジュールも必要になります。Redis は Python オブジェクトをキャッシュに保存できないため、pickle を使用して最新のアクセス リストをマーシャルします。そのため、これもインポートします。Memcache のメリットの 1 つは、オブジェクトのシリアル化が自動的に行われることです。一方、Memorystore はもう少し「DIY」です。最後に、google.appengine.ext.ndb を google.cloud.ndb に置き換えて、App Engine ndb から Cloud NDB にアップグレードします。これらの変更を行うと、インポートは次のようになります。
変更後:
import os
import pickle
from flask import Flask, render_template, request
from google.cloud import ndb
import redis
初期化を更新
モジュール 12 の初期化では、Flask アプリケーション オブジェクト app をインスタンス化し、1 時間分のキャッシュ保存の定数を設定します。
変更前:
app = Flask(__name__)
HOUR = 3600
Cloud API を使用するにはクライアントが必要なので、Flask の直後に Cloud NDB クライアントをインスタンス化します。次に、app.yaml で設定した環境変数から Memorystore インスタンスの IP アドレスとポート番号を取得します。この情報を使用して、Redis クライアントをインスタンス化します。更新後のコードは次のようになります。
変更後:
app = Flask(__name__)
ds_client = ndb.Client()
HOUR = 3600
REDIS_HOST = os.environ.get('REDIS_HOST', 'localhost')
REDIS_PORT = os.environ.get('REDIS_PORT', '6379')
REDIS = redis.Redis(host=REDIS_HOST, port=REDIS_PORT)
*Python 3 への移行
このセクションは省略可能です。モジュール 12 アプリの Python 3 バージョンから始める場合は、インポートと初期化に関連するいくつかの必要な変更があります。
まず、Memcache は App Engine バンドル サービスであるため、Python 3 アプリで使用するには App Engine SDK が必要です。具体的には、WSGI アプリケーションをラップします(他の必要な構成も同様です)。
変更前:
from flask import Flask, render_template, request
from google.appengine.api import memcache, wrap_wsgi_app
from google.appengine.ext import ndb
app = Flask(__name__)
app.wsgi_app = wrap_wsgi_app(app.wsgi_app)
HOUR = 3600
Cloud Memorystore(Memcache などの App Engine バンドル サービスではない)に移行するため、SDK の使用を削除する必要があります。これは、memcache と wrap_wsgi_app の両方をインポートする行全体を削除するだけなので、簡単です。wrap_wsgi_app() を呼び出す行も削除します。これらの更新により、アプリのこの部分(実際にはアプリ全体)は Python 2 バージョンと同じになります。
変更後:
import os
import pickle
from flask import Flask, render_template, request
from google.cloud import ndb
import redis
app = Flask(__name__)
ds_client = ndb.Client()
HOUR = 3600
REDIS_HOST = os.environ.get('REDIS_HOST', 'localhost')
REDIS_PORT = os.environ.get('REDIS_PORT', '6379')
REDIS = redis.Redis(host=REDIS_HOST, port=REDIS_PORT)
最後に、app.yaml(app_engine_apis: true 行を削除)と requirements.txt(appengine-python-standard 行を削除)から SDK の使用を削除します。
Cloud Memorystore(および Cloud NDB)に移行する
Cloud NDB のデータモデルは App Engine ndb と互換性があるように設計されています。つまり、Visit オブジェクトの定義は同じままです。モジュール 2 の Cloud NDB への移行を模倣して、store_visit() と fetch_visits() のすべての Datastore 呼び出しが拡張され、新しい with ブロックに埋め込まれます(Cloud NDB コンテキスト マネージャーの使用が必要なため)。変更前の呼び出しは次のとおりです。
変更前:
def store_visit(remote_addr, user_agent):
'create new Visit entity in Datastore'
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
def fetch_visits(limit):
'get most recent visits'
return Visit.query().order(-Visit.timestamp).fetch(limit)
両方の関数に with ds_client.context() ブロックを追加し、Datastore 呼び出しをその内側に(インデントして)配置します。この場合、呼び出し自体に変更を加える必要はありません。
変更後:
def store_visit(remote_addr, user_agent):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
def fetch_visits(limit):
'get most recent visits'
with ds_client.context():
return Visit.query().order(-Visit.timestamp).fetch(limit)
次に、キャッシュ保存の変更点を見ていきましょう。モジュール 12 の main() 関数は次のとおりです。
変更前:
@app.route('/')
def root():
'main application (GET) handler'
# check for (hour-)cached visits
ip_addr, usr_agt = request.remote_addr, request.user_agent
visitor = '{}: {}'.format(ip_addr, usr_agt)
visits = memcache.get('visits')
# register visit & run DB query if cache empty or new visitor
if not visits or visits[0].visitor != visitor:
store_visit(ip_addr, usr_agt)
visits = list(fetch_visits(10))
memcache.set('visits', visits, HOUR) # set() not add()
return render_template('index.html', visits=visits)
Redis には、Memcache と同様に「get」呼び出しと「set」呼び出しがあります。それぞれのクライアント ライブラリを入れ替えるだけですよね?ほぼ正確です。前述のように、Redis で Python リストをキャッシュに保存することはできません(最初にシリアル化する必要があるため。Memcache はこれを自動的に処理します)。そのため、set() 呼び出しで、pickle.dumps() を使用してアクセス数を文字列に pickle 化します。同様に、キャッシュからアクセスを取得する場合は、get() の直後に pickle.loads() でアンピクルする必要があります。これらの変更を実装した後のメイン ハンドラは次のようになります。
変更後:
@app.route('/')
def root():
'main application (GET) handler'
# check for (hour-)cached visits
ip_addr, usr_agt = request.remote_addr, request.user_agent
visitor = '{}: {}'.format(ip_addr, usr_agt)
rsp = REDIS.get('visits')
visits = pickle.loads(rsp) if rsp else None
# register visit & run DB query if cache empty or new visitor
if not visits or visits[0].visitor != visitor:
store_visit(ip_addr, usr_agt)
visits = list(fetch_visits(10))
REDIS.set('visits', pickle.dumps(visits), ex=HOUR)
return render_template('index.html', visits=visits)
これで、main.py でサンプルアプリの Memcache の使用を Cloud Memorystore に変換するために必要な変更は完了です。HTML テンプレートと Python 3 への移植はどうなりますか?
HTML テンプレート ファイルを更新して Python 3 に移植する
サプライズ!このアプリケーションは、コードの変更や互換性ライブラリなしで Python 2 と 3 の両方で実行できるように設計されているため、ここでは何もする必要はありません。main.py が表示されます。mod13a(2.x)と mod13b(3.x)の「FINISH」フォルダで同じです。requirements.txt も同様です(バージョン番号が異なる場合を除く)。ユーザー インターフェースは変更されないため、templates/index.html も更新されません。
Python 3 App Engine でこのアプリを実行するために必要なすべての作業は、構成で完了しました。不要なディレクティブは app.yaml から削除され、appengine_config.py と lib フォルダは Python 3 で使用されていないため削除されました。
7. 概要/クリーンアップ
このセクションでは、アプリをデプロイし、意図したとおりに動作することと、出力に反映されることを確認して、この Codelab を終了します。アプリの検証が完了したら、クリーンアップを行い、次のステップを検討します。
アプリケーションをデプロイして検証する
最後のチェックは、常にサンプルアプリをデプロイすることです。Python 2 デベロッパーは、次のコマンドを使用して lib を削除して再インストールします。(システムに Python 2 と 3 の両方がインストールされている場合は、代わりに pip2 を明示的に実行する必要がある場合があります)。
rm -rf ./lib pip install -t lib -r requirements.txt
Python 2 と 3 の両方のデベロッパーは、アプリをデプロイする際に次のコマンドを使用する必要があります。
gcloud app deploy
内部で完全に異なるキャッシュ サービスに配線を変更しただけなので、アプリ自体はモジュール 12 のアプリと同じように動作します。

これで、この Codelab は完了です。更新したサンプルアプリを、モジュール 13 のフォルダ mod13a(Python 2)または mod13b(Python 3)のいずれかと比較してください。
クリーンアップ
全般
現時点で完了した場合は、課金が発生しないように App Engine アプリを無効にすることをおすすめします。ただし、さらにテストや実験を行う場合は、App Engine プラットフォームに無料割り当てがあります。この使用量枠を超えない限り、課金されることはありません。これはコンピューティングの料金ですが、関連する App Engine サービスの料金も発生する可能性があります。詳細については、料金ページをご覧ください。この移行に他の Cloud サービスが含まれる場合は、それらのサービスは別途請求されます。どちらの場合も、該当する場合は、以下の「この Codelab に固有」のセクションをご覧ください。
完全に開示すると、App Engine などの Google Cloud サーバーレス コンピューティング プラットフォームにデプロイすると、ビルドとストレージの費用がわずかに発生します。Cloud Build には独自の無料割り当てがあり、Cloud Storage にも独自の無料割り当てがあります。そのイメージの保存には、その割り当ての一部が使用されます。ただし、お住まいの地域でこのような無料枠が提供されていない可能性もあります。そのため、保存容量の使用状況を把握して、費用を最小限に抑えるようにしてください。確認する必要がある特定の Cloud Storage の「フォルダ」は次のとおりです。
console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/imagesconsole.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com- 上記のストレージ リンクは、
PROJECT_IDと *LOC*ーションによって異なります。たとえば、アプリが米国でホストされている場合は「us」になります。
ただし、このアプリケーションや関連する移行 Codelab を続行せず、すべてを完全に削除する場合は、プロジェクトをシャットダウンしてください。
この Codelab に固有
以下のサービスは、この Codelab 固有のものです。詳細については、各プロダクトのドキュメントをご覧ください。
- Cloud Memorystore にはインスタンスが必要であり、無料枠はありません。使用料金の詳細については、料金ページをご覧ください。
- Cloud Serverless VPC Access コネクタにはインスタンスが必要であり、無料枠はありません。使用料金の詳細については、Cloud VPC の料金ページの該当するセクションをご覧ください。
- Cloud Datastore(Datastore モードの Cloud Firestore)には無料枠があります。詳細については、料金ページをご覧ください。
このチュートリアルでは、次の 4 つの Cloud プロダクトを使用しました。
- App Engine
- Cloud Datastore
- Cloud Memorystore
- Cloud VPC
以下に、これらのリソースを解放して課金を回避または最小限に抑える手順を示します。
Memorystore インスタンスと VPC コネクタをシャットダウンする
これらのプロダクトには無料枠がないため、現在、請求が発生しています。Cloud プロジェクトをシャットダウンしない場合(次のセクションを参照)、課金を停止するには、Memorystore インスタンスと VPC コネクタの両方を削除する必要があります。これらのリソースを作成したときと同様に、Cloud コンソールまたはコマンドラインからリリースすることもできます。
Cloud コンソールから
Memorystore インスタンスを削除するには、Memorystore ダッシュボードに戻り、インスタンス ID をクリックします。

インスタンスの詳細ページで、[削除] をクリックして確定します。
VPC コネクタを削除するには、そのダッシュボードに移動し、削除するコネクタの横にあるチェックボックスをオンにして、[削除] をクリックして確認します。

コマンドラインから
次の gcloud コマンドのペアは、それぞれ Memorystore インスタンスと VPC コネクタを削除します。
gcloud redis instances delete INSTANCE --region REGIONgcloud compute networks vpc-access connectors delete CONNECTOR --region REGION
gcloud config set project でプロジェクト ID を設定していない場合は、--project PROJECT_ID を指定する必要があります。Memorystore インスタンスの名前が demo-ms、VPC コネクタの名前が demo-vpc で、両方がリージョン us-central1 にある場合は、次のコマンドのペアを発行して確認します。
$ gcloud redis instances delete demo-ms --region us-central1 You are about to delete instance [demo-ms] in [us-central1]. Any associated data will be lost. Do you want to continue (Y/n)? Delete request issued for: [demo-ms] Waiting for operation [projects/PROJECT/locations/REGION/operations/operation-aaaaa-bbbbb-ccccc-ddddd] to complete...done. Deleted instance [demo-ms]. $ $ gcloud compute networks vpc-access connectors delete demo-vpc --region us-central1 You are about to delete connector [demo-vpc] in [us-central1]. Any associated data will be lost. Do you want to continue (Y/n)? Delete request issued for: [demo-vpc] Waiting for operation [projects/PROJECT/locations/REGION/operations/aaaaa-bbbb-cccc-dddd-eeeee] to complete...done. Deleted connector [demo-vpc].
各リクエストの実行には数分かかります。前述のように Cloud プロジェクト全体をシャットダウンする場合は、これらの手順は省略可能ですが、シャットダウン プロセスが完了するまでは課金が発生します。
次のステップ
このチュートリアル以外にも、以前のバンドル サービスからの移行に焦点を当てた移行モジュールがあります。
- モジュール 2: App Engine
ndbから Cloud NDB に移行する - モジュール 7 ~ 9: App Engine タスクキューの push タスクから Cloud Tasks に移行する
- モジュール 12 ~ 13: App Engine Memcache から Cloud Memorystore への移行
- モジュール 15 ~ 16: App Engine Blobstore から Cloud Storage への移行
- モジュール 18 ~ 19: App Engine タスクキュー(pull タスク)から Cloud Pub/Sub に移行する
App Engine は、Google Cloud の唯一のサーバーレス プラットフォームではなくなりました。小規模な App Engine アプリや、機能が制限されているアプリをスタンドアロンのマイクロサービスに変換したい場合や、モノリシック アプリを複数の再利用可能なコンポーネントに分割したい場合は、Cloud Functions への移行を検討する理由として十分です。コンテナ化がアプリケーション開発ワークフローの一部になっている場合(特に CI/CD(継続的インテグレーション/継続的デリバリーまたはデプロイ)パイプラインで構成されている場合)は、Cloud Run への移行を検討してください。これらのシナリオは、次のモジュールで取り上げます。
- App Engine から Cloud Functions に移行する: モジュール 11 をご覧ください。
- App Engine から Cloud Run に移行する: モジュール 4 で Docker を使用してアプリをコンテナ化するか、モジュール 5 でコンテナ、Docker の知識、
Dockerfileを使用せずにコンテナ化します。
別のサーバーレス プラットフォームへの切り替えは任意です。変更を行う前に、アプリとユースケースに最適なオプションを検討することをおすすめします。
次にどの移行モジュールを検討する場合でも、すべてのサーバーレス移行ステーションのコンテンツ(Codelab、動画、ソースコード [利用可能な場合])は、オープンソース リポジトリからアクセスできます。リポジトリの README には、考慮すべき移行と、移行モジュールの関連する「順序」に関するガイダンスも記載されています。
8. 参考情報
以下に、デベロッパーがこの移行モジュールまたは関連する移行モジュールや関連プロダクトをさらに詳しく調べるための追加リソースを示します。このコンテンツに関するフィードバックを送信できる場所、コードへのリンク、役立つ可能性のあるさまざまなドキュメントなどが含まれます。
Codelab に関する問題/フィードバック
この Codelab に問題が見つかった場合は、提出する前にまず問題を検索してください。新しい問題の検索と登録を行うためのリンク:
移行に関するリソース
モジュール 12(開始)とモジュール 13(終了)のリポジトリ フォルダへのリンクを以下の表に示します。これらのフォルダには、すべての App Engine Codelab 移行のリポジトリからアクセスすることもでき、クローンを作成する、または ZIP ファイルをダウンロードすることができます。
Codelab | Python 2 | Python 3 |
モジュール 13(この Codelab) |
オンライン リファレンス
このチュートリアルに関連する可能性のあるオンライン リソースは次のとおりです。
App Engine
- App Engine のドキュメント
- Python 2 App Engine(標準環境)ランタイム
- Python 2 App Engine で App Engine の組み込みライブラリを使用する
- Python 3 App Engine(スタンダード環境)ランタイム
- Python 2 と 3 の App Engine(スタンダード環境)ランタイムの違い
- Python 2 から 3 への App Engine(スタンダード環境)移行ガイド
- App Engine の料金と割り当てに関する情報
App Engine NDB と Cloud NDB
- App Engine NDB の概要
- App Engine NDB Datastore の使用量
- Google Cloud NDB ドキュメント
- Google Cloud NDB リポジトリ
- Cloud Datastore の料金情報
App Engine Memcache と Cloud Memorystore
- App Engine Memcache の概要
- Python 2 App Engine
memcacheリファレンス - Python 3 App Engine
memcacheリファレンス - App Engine
memcacheから Cloud Memorystore への移行ガイド - Cloud Memorystore のドキュメント
- Cloud Memorystore for Redis のドキュメント
- Cloud Memorystore for Redis の料金情報
- Cloud Memorystore でサポートされている Redis バージョン
- Cloud Memorystore のホームページ
- Cloud コンソールで新しい Memorystore インスタンスを作成する
- Python Redis クライアントのホームページ
- Python Redis クライアント ライブラリのドキュメント
Cloud VPC
- Google Cloud VPC ドキュメント
- Google Cloud VPC のホームページ
- Cloud VPC の料金情報
- Cloud コンソールで新しいサーバーレス VPC アクセス コネクタを作成する
その他のクラウド情報
- Google Cloud Platform での Python
- Google Cloud Python クライアント ライブラリ
- Google Cloud の「常時無料」枠
- Google Cloud SDK(
gcloudコマンドライン ツール) - Google Cloud に関するすべてのドキュメント
ライセンス
この作業はクリエイティブ・コモンズの表示 2.0 汎用ライセンスにより使用許諾されています。
