Flask アプリで App Engine Memcache を使用する方法(モジュール 12)

1. 概要

Serverless Migration Station の Codelab シリーズ(セルフペース型のハンズオン チュートリアル)と関連動画は、Google Cloud サーバーレス デベロッパーが主にレガシー サービスからの移行を 1 つ以上の移行を通じてガイドし、アプリをモダナイズできるようにすることを目的としています。これにより、アプリのポータビリティが高まり、選択肢と柔軟性が増し、より広範な Cloud プロダクトと統合してアクセスできるようになり、より新しい言語リリースに簡単にアップグレードできるようになります。当初は初期の Cloud ユーザー、主に App Engine(スタンダード環境)のデベロッパーを対象としていますが、Cloud FunctionsCloud Run など、その他のサーバーレス プラットフォーム(該当する場合)まで幅広くカバーしています。

この Codelab では、モジュール 1 CodelabサンプルアプリApp Engine Memcache を追加して使用する方法を説明します。モジュール 12 のチュートリアルで Memcache の使用について説明した後、モジュール 13 で Cloud Memorystore への移行について説明します。

GCP コンソールの

  • App Engine Memcache API/ライブラリを使用する
  • 基本的な Python 2 Flask App Engine NDB アプリにキャッシュを追加する

必要なもの

アンケート

このチュートリアルをどのように使用されますか?

通読のみ 通読して演習を行う

Python のご利用経験はどの程度ありますか?

初心者 中級者 上級者

Google Cloud サービスの使用経験はどの程度ありますか?

<ph type="x-smartling-placeholder"></ph> 初心者 中級 上達 をご覧ください。

2. 背景情報

App Engine Memcache から移行するには、モジュール 1 Codelab で作成した既存の Flask と App Engine NDB アプリに Memcache の使用方法を追加します。このサンプルアプリでは、直近 10 件のユーザー訪問を表示します。同じユーザーがブラウザを更新する場合、新しい Visit エンティティを継続的に作成して Datastore から最新の訪問を取得することはおすすめしません。そのため、これらの最近の訪問をキャッシュに保存することになります。

同じユーザーがページにアクセスした場合、これらのアクセスはキャッシュから返されます。新しいユーザーがサイトにアクセスするか、1 時間が経過すると、キャッシュはフラッシュされ、最新のエントリで置き換えられます(新規訪問の登録は言うまでもありません)。この App Engine Memcache インテグレーションを実装したら、次の Codelab(モジュール 13)で Cloud Memorystore に移行できます。

このチュートリアルでは、次の手順について説明します。

  1. セットアップ / 事前作業
  2. 構成の更新
  3. アプリケーション コードを変更する

3. 設定/事前作業

チュートリアルの主要部分に進む前に、プロジェクトを設定し、コードを取得してから、ベースライン アプリをデプロイして、コードの作業を開始できるようにします。

1. プロジェクトのセットアップ

モジュール 1 の Codelab を完了している場合は、同じプロジェクト(およびコード)を再利用することをおすすめします。あるいは、新しいプロジェクトを作成することも、別の既存のプロジェクトを再利用することもできます。プロジェクトに有効な請求先アカウントがあり、App Engine が有効になっていることを確認します。

2. ベースラインのサンプルアプリを取得する

この Codelab の前提条件の一つは、機能するモジュール 1 サンプルアプリがあることです。まだお持ちでない場合は、先に進む前に、いずれかのチュートリアル(上のリンク)を完了してください。すでにその内容に慣れている場合は、以下のモジュール 1 のコードから始めてもかまいません。

ご自分のコードと Google で用意したコードのいずれを使用される場合も、モジュール 1 のコードから開始します。この Codelab では各ステップについて説明します。最後に、モジュール 11 のリポジトリ フォルダ(FINISH)にあるコードと同様のコードを使用して締めくくります。

モジュール 1 の開始ファイルのディレクトリ(ご自身またはこちら)は次のようになります。

$ ls
README.md               main.py                 templates
app.yaml                requirements.txt

3. ベースライン アプリを(再)デプロイする

この段階で実施する必要がある残りの事前作業のステップ:

  1. gcloud コマンドライン ツールを学びなおす
  2. gcloud app deploy を使用してサンプルアプリを再デプロイする
  3. アプリが App Engine で問題なく動作することを確認する

これらのステップを正常に実行し、ウェブアプリが動作することを確認したら(次のような出力が表示されます)、アプリにキャッシュ機能を追加できます。

a7a9d2b80d706a2b.png

4. 構成の更新

標準の App Engine 構成ファイル(app.yamlrequirements.txtappengine_config.py)を変更する必要はありません。

5. アプリケーション ファイルを変更する

ここでは App Engine API を追加するだけなので、外部パッケージは関係ありません。つまり、構成ファイル(app.yamlrequirements.txtappengine_config.py)を更新する必要はありません。アプリケーション ファイルは main.py という 1 つしかないため、このセクションで行った変更はすべてそのファイルにのみ影響します。

インポート

最も重要なステップは、Memcache ライブラリ google.appengine.api.memcache のインポートです。最近のアクセスを 1 時間キャッシュに保存するため、1 時間の秒数を表す定数も追加します。変更後のコードは次のようになります。

変更前:

from flask import Flask, render_template, request
from google.appengine.ext import ndb

app = Flask(__name__)

変更後:

from flask import Flask, render_template, request
from google.appengine.api import memcache
from google.appengine.ext import ndb

app = Flask(__name__)
HOUR = 3600

Memcache のサポートによるキャッシュの追加

最も重要な変更は、アプリケーションでキャッシュの使用を追加したことです。具体的には、直近の訪問をキャッシュし、キャッシュされた訪問が使用可能かどうかを確認したうえで、計画に沿って可能な限りキャッシュ内の結果を利用するようにします。この目標を達成するためにアプリが実行するステップは次のとおりです。

  1. 現在の訪問を設定し、「visitor」という名前を付けます。
  2. 最新の visits をキャッシュから取得する
  3. キャッシュが空の場合、または最新の訪問者(visits[0]['visitor'])が現在の visitor と異なる場合は、この最新の訪問を保存し、最新の訪問を取得し、1 時間キャッシュします。
  4. ウェブ テンプレートを使用してユーザーに visits を表示する

更新前と変更後は次のとおりです。

変更前:

@app.route('/')
def root():
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10)
    return render_template('index.html', visits=visits)

変更後:

@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)

以下に、変更点を画像で示します。

b1242503602f7bf0.png

これで、モジュール 1 サンプルアプリで App Engine memcache の使用を追加するために必要な変更はすべて完了です。このアプリをビルドしてデプロイし、動作することを確認します。

6. 概要/クリーンアップ

このセクションでは、この Codelab の締めくくりとして、アプリをデプロイし、意図したとおりに動作することを確認し、反映された出力を確認します。アプリの検証後、クリーンアップ手順を実施し、次のステップを検討します。

アプリケーションのデプロイと検証

gcloud app deploy を使用してアプリを再デプロイし、アプリが動作していることを確認します。コードが FINISH(モジュール 12 フォルダ)のコードと一致しているはずです。出力は、先ほどデプロイしたモジュール 1 のアプリと同じになるはずです。

a7a9d2b80d706a2b.png

私たちが行ったのは、同じユーザーのユーザー エクスペリエンスを高速化することだけです。キャッシュを更新すると、キャッシュから直接結果を取得できます。キャッシュでは、新しい訪問を作成したり、Datastore のフェッチを行ったりすることはありません。

お疲れさまでした。以上で、モジュール 12 の Codelab は以上で、App Engine memcache サービスの使用をサンプル アプリケーションに追加する方法を学習しました。ボーナスのステップで、この Python 2 アプリを Python 3 に移植できるようになりました。

クリーンアップ

全般

現時点で完了したら、課金が発生しないように App Engine アプリを無効にすることをおすすめします。さらにテストや実験を行う場合は、App Engine プラットフォームに無料の割り当てが用意されています。この使用量ティアを超えない限り、料金は発生しません。これはコンピューティングに関するものですが、関連する App Engine サービスに対して料金が発生する場合もあります。詳細については、料金ページをご覧ください。この移行に他のクラウド サービスが含まれる場合、それらは別途請求されます。いずれの場合も、該当する場合は「この Codelab に固有の情報」をご覧ください。セクションをご覧ください。

App Engine のような Google Cloud サーバーレス コンピューティング プラットフォームにデプロイすると、わずかなビルドとストレージの費用が発生します。Cloud Build には、Cloud Storage と同様に無料の割り当てがあります。イメージのストレージが割り当ての一部を使い果たします。ただし、このような無料枠がない地域に住んでいる可能性もあるため、潜在的な費用を最小限に抑えるためにストレージの使用量に注意してください。特定の Cloud Storage「フォルダ」確認すべき項目には

  • console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/images
  • console.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com
  • 上記のストレージ リンクは、ご利用の PROJECT_ID と *LOC*に依存します(例: 「us」)アプリが米国でホストされている場合は、

一方、このアプリケーションや他の関連する移行 Codelab を続行せず、すべてを完全に削除したい場合は、プロジェクトをシャットダウンします。

この Codelab のみ

以下に示すサービスは、この Codelab に固有のものです。詳細については、各プロダクトのドキュメントをご覧ください。

  • App Engine Memcache サービスには 2 種類があり、それぞれに独自の料金体系があります。そのため、利用を課金と関連付けて追跡する必要があります。
  • App Engine Datastore サービスは Cloud Datastore(Datastore モードの Cloud Firestore)で提供しており、これにも無料枠があります。詳しくは料金ページをご覧ください。

次のステップ

次に検討すべき論理移行については、モジュール 13 で説明します。ここでは、App Engine memcache サービスから Cloud Memorystore に移行する方法について説明しています。これらの移行はすべて任意であり、ユーザーはアプリケーションをモダナイズするためにさまざまな手順を踏むことができます。Cloud Memorystore サービスは、さまざまな理由から、App Engine の memcache を大幅にアップグレードするものです。

  • Cloud Memorystore はサーバーレスではありません。つまり、キャッシュ用のサーバーを割り当てる必要があります。また、Cloud Memorystore に無料枠はありません。どちらの要因も費用に大きな影響を与える可能性があります。
  • Cloud Memorystore は、基盤となるさまざまなストレージ メカニズム(キャッシュ エンジン)である RedisMemcached のペアをサポートしています。
  • Cloud Memorystore(for Redis)は、App Engine Memcache よりもはるかに豊富で詳細な機能セットを備えています。
  • Cloud Memorystore を使用するには、Cloud Memorystore サーバーをセットアップして Google Cloud VPC ネットワークに追加し、App Engine アプリでそのネットワークを使用して Memorystore サーバーと通信する必要があります。

Cloud Memorystore のすべての機能が必要ではない場合、または費用への影響が心配な場合は、App Engine Memcache を引き続き使用できます。

モジュール 13 以外にも、Cloud NDB や Cloud Datastore、Cloud Tasks など、考えられる移行は多数あります。また、Cloud Run と Cloud Functions へのプロダクト間の移行もあります。すべて移行リポジトリにあります。

次のステップとして Python 3 への移植も考えられます。これについては、次のセクションでオプションのステップとして取り上げます。

7. 参考: Python 3 への移行

概要

このセクションには、上で終了したモジュール 12 アプリケーションを Python 3 に移行するボーナス コンテンツが含まれています。まず構成から始め、次にアプリケーションがあります。

app.yaml を簡素化する

Python 3 ランタイムの利点の一つは、app.yaml を大幅に簡素化できることです。

変更前:

モジュール 12 の最後にある app.yaml の内容は次のとおりです。

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

Python 3 ランタイムでは、ウェブ フレームワークが独自のルーティングを行う必要があるため、app.yaml のすべてのルートハンドラを auto に変更する必要があります。提供される静的ファイルがない場合は、handlers: セクション全体を完全に削除できます。また、threadsafeapi_version の両方が非推奨になりました

変更後:

前述の必要な変更により、これは Python 3 の app.yaml の代わりとなります。

runtime: python39
app_engine_apis: true

説明が必要な行は app_engine_apis: true のみです。2021 年に以前の App Engine サービスが第 2 世代ランタイムで利用可能になった時点で、Python 3 を含む一部のランタイムでは、これらの API(ndbtaskqueuememcache など)にアクセスするために追加のブートストラップが必要になります。この構成のこの行は、この目的にかなっています。

requirements.txt を更新する

requirements.txt では、元の API の別のブートストラップが必要です。新しい App Engine SDK へのアクセスを含める必要があります。

変更前:

モジュール 12 の最後にある app.yaml の内容は次のとおりです。

flask

変更後:

App Engine Python SDK を追加するだけで、次のようになっているはずです。

flask
appengine-python-standard

appengine_config.py と lib の削除

次世代の App Engine ランタイムでは、サードパーティ パッケージの使用が次のように刷新されます。

  • 組み込みライブラリとは、Google によって審査され、App Engine サーバーで利用可能なライブラリのことです。組み込みライブラリには、クラウドへのデプロイが許可されていない C/C++ コードが含まれていることが理由と考えられます。組み込みライブラリは、第 2 世代のランタイムでは使用できません。
  • 第 2 世代のランタイムでは、非組み込みライブラリ(「ベンダリング」や「セルフバンドル」と呼ばれることもあります)のコピーが不要になりました。代わりに、requirements.txt にリストされているはずです。デプロイ時にビルドシステムによって自動的にインストールされます。

サードパーティのパッケージ管理を変更した結果、appengine_config.py ファイルと lib フォルダは必要ないので、削除します。第 2 世代のランタイムでは、App Engine は requirements.txt にリストされているサードパーティ パッケージを自動的にインストールします。要約:

  1. セルフバンドルまたはコピーされたサードパーティ ライブラリは存在しない。requirements.txt にリストする
  2. lib フォルダに pip install が含まれていない(つまり、lib フォルダのピリオドがない)
  3. app.yaml にサードパーティ ライブラリの組み込みリストがない(したがって libraries セクションがない)。requirements.txt にリストアップする
  4. アプリから参照するサードパーティ ライブラリがないため、appengine_config.py ファイルはありません。

デベロッパーの要件は、必要なサードパーティ ライブラリをすべて requirements.txt にリストすることです。

App Engine SDK を使用するようにアプリケーションを更新する

前述のように、Python 3 アプリで App Engine バンドル サービスにアクセスするには、いくつかの変更が必要です。

  1. App Engine SDK をバンドルする(requirements.txt
  2. App Engine SDK を有効にする(app.yaml
  3. WSGI オブジェクトをラップする(main.py 内)

最初のペアはここまでで完了しているため、最後の要件は main.py の更新です。

変更前:

以下は、モジュール 12 の最後にある Python 2 の main.py です。

from flask import Flask, render_template, request
from google.appengine.api import memcache
from google.appengine.ext import ndb

app = Flask(__name__)
HOUR = 3600

変更後:

Python 3 ポートの場合は、SDK をインポートし、それで Flask アプリ オブジェクトをラップします(SDK ラッパー)。結果は次のようになります。

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

デベロッパーが 2.x から 3.x に移行する場合、バンドル サービスにアクセスするには、Python アプリに対して次の変更を行う必要があります。Flask を使用していない場合、ドキュメントに Django と Pyramid のサンプルもあります。Python 2 コードがウェブアプリでない場合、Python 3 に移植する際は SDK パッケージを含めるだけで十分です。このアプリケーション コードは元々 Python 2 と Python 3 で動作するように作成されたものなので、追加の互換性の変更は必要ありません。

アプリケーションのデプロイ

上記の変更が完了したら、更新したサンプルアプリをデプロイできます。(同じ GCP プロジェクトで、アプリの Python 3 バージョンを元の Python 2 バージョンの上にデプロイしても問題はありません)。アプリの動作は変わらない。更新したアプリを Google のアプリと比較する必要がある場合は、移行リポジトリの Module 12b フォルダをご覧ください。Python 3 などの最新のランタイムでの App Engine バンドル サービスのサポートの詳細については、機能のリリースに関するお知らせモジュール 17 の Codelab をご覧ください。

おめでとうございます。モジュール 12 のボーナス ステップを完了しました。Python 3 ランタイム用の構成ファイルの準備に関するドキュメントもご覧ください。次のステップとクリーンアップについては、上記の概要/クリーンアップのセクションをご覧ください。

8. 参考情報

以下に、本モジュールや関連する移行モジュールと関連プロダクトについて詳しく学ぶデベロッパー向けの追加リソースを示します。これには、このコンテンツに関するフィードバックを提供する場所、コードへのリンク、役立つさまざまなドキュメントが含まれます。

Codelab の問題/フィードバック

この Codelab に問題が見つかった場合は、提出する前にまず問題を検索してください。新しい問題の検索と登録を行うためのリンク:

移行に関するリソース

以下の表に、モジュール 2(START)とモジュール 12(FINISH)のリポジトリ フォルダへのリンクを示します。これらは、すべての App Engine Codelab 移行用のリポジトリからもアクセスでき、ZIP ファイルのクローンを作成したりダウンロードしたりできます。

Codelab

Python 2

Python 3

モジュール 1

コード

code(このチュートリアルでは取り上げません)

モジュール 12(この Codelab)

コード

コード

オンライン リファレンス

このチュートリアルに関連する可能性のあるオンライン リソースは次のとおりです。

App Engine

Cloud Memorystore と Cloud Datastore

Cloud のその他の情報

動画

ライセンス

この作業はクリエイティブ・コモンズの表示 2.0 汎用ライセンスにより使用許諾されています。