Firestore でのセッション処理

多くのアプリには、認証設定とユーザー設定用のセッション処理が必要です。Flask フレームワークには、この機能を実行するためのメモリベースの実装が付属しています。ただし、記録されるセッションがインスタンス間で異なる場合があるため、この実装は複数のインスタンスから提供できるアプリには適していません。このチュートリアルでは、App Engine でセッションを処理する方法を示します。

目標

  • アプリを作成する。
  • アプリをローカルで実行する。
  • App Engine にアプリをデプロイする。

料金

このチュートリアルでは、課金対象である次の Google Cloud コンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。新しい Google Cloud ユーザーは無料トライアルをご利用いただけます。

このチュートリアルを終了した後、作成したリソースを削除すると、それ以上の請求は発生しません。詳しくは、クリーンアップをご覧ください。

始める前に

  1. Google アカウントにログインします。

    Google アカウントをまだお持ちでない場合は、新しいアカウントを登録します。

  2. Cloud Console のプロジェクト セレクタページで、Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタのページに移動

  3. Google Cloud プロジェクトに対して課金が有効になっていることを確認します。プロジェクトに対して課金が有効になっていることを確認する方法を学習する

  4. Firestore API を有効にします。

    API を有効にする

  5. Cloud SDK をインストールして初期化します。
  6. Python、pipvirtualenv をシステムにインストールします。手順については、Google Cloud 用の Python 開発環境の設定をご覧ください。

プロジェクトの設定

  1. ターミナル ウィンドウで、選択したディレクトリに移動し、sessions という名前の新しいディレクトリを作成します。このチュートリアルのコードはすべて、sessions ディレクトリ内にあります。

  2. sessions ディレクトリに移動します。

    cd sessions
    
  3. 次の内容で requirements.txt を作成します。

    google-cloud-firestore==1.9.0
    flask==1.1.2
    
  4. 依存関係をインストールします。

    pip install  -r requirements.txt
    

このチュートリアルの最後では、最終的なファイル構造が次のようになります。

sessions
├── app.yaml
├── main.py
└── requirements.txt

ウェブアプリの作成

このアプリは、ユーザーごとに異なる言語で挨拶を表示します。リピーターは常に同じ言語で挨拶されます。

さまざまな言語で挨拶が表示されている複数のアプリ ウィンドウ。

アプリでユーザーの設定を保存するには、現在のユーザーに関する情報をセッションに保存する方法が必要です。このサンプルアプリは、Firestore を使用してセッション データを保存します。

  • ターミナル ウィンドウで、次の内容の main.py という名前のファイルを作成します。

    import random
    from uuid import uuid4
    
    from flask import Flask, make_response, request
    from google.cloud import firestore
    
    app = Flask(__name__)
    db = firestore.Client()
    sessions = db.collection('sessions')
    greetings = [
        'Hello World',
        'Hallo Welt',
        'Ciao Mondo',
        'Salut le Monde',
        'Hola Mundo',
    ]
    
    @firestore.transactional
    def get_session_data(transaction, session_id):
        """ Looks up (or creates) the session with the given session_id.
            Creates a random session_id if none is provided. Increments
            the number of views in this session. Updates are done in a
            transaction to make sure no saved increments are overwritten.
        """
        if session_id is None:
            session_id = str(uuid4())   # Random, unique identifier
    
        doc_ref = sessions.document(document_id=session_id)
        doc = doc_ref.get(transaction=transaction)
        if doc.exists:
            session = doc.to_dict()
        else:
            session = {
                'greeting': random.choice(greetings),
                'views': 0
            }
    
        session['views'] += 1   # This counts as a view
        transaction.set(doc_ref, session)
    
        session['session_id'] = session_id
        return session
    
    @app.route('/', methods=['GET'])
    def home():
        template = '<body>{} views for "{}"</body>'
    
        transaction = db.transaction()
        session = get_session_data(transaction, request.cookies.get('session_id'))
    
        resp = make_response(template.format(
            session['views'],
            session['greeting']
            )
        )
        resp.set_cookie('session_id', session['session_id'], httponly=True)
        return resp
    
    if __name__ == '__main__':
        app.run(host='127.0.0.1', port=8080)
  • 次の図は、Firestore が App Engine アプリ用のセッションを処理する方法を示しています。

    アーキテクチャの図: ユーザー、App Engine、Firestore。

app.use(session) を設定すると、すべてのリクエストが req.session プロパティを持つようになり、このプロパティを使用してリピーターを特定できます。セッション データは Firestore に保存されます。

セッションの削除

セッション データを削除するか、自動削除戦略を実装できます。セッションに、Memcache や Redis などのストレージ ソリューションを使用すると、期限切れのセッションが自動的に削除されます。

ローカルでの実行

  1. ターミナル ウィンドウで、Gunicorn HTTP サーバーをインストールします。

    pip install gunicorn
    
  2. Gunicorn HTTP サーバーを実行します。

    gunicorn -b :8080 main:app
    
  3. ウェブブラウザでアプリを表示します。

    Cloud Shell

    Cloud Shell ツールバーの [ウェブでプレビュー] ウェブでプレビュー アイコンをクリックし、[ポート 8080 でプレビュー] を選択します。

    ローカルマシン

    ブラウザで、http://localhost:8080 にアクセスします。

    「Hello World」、「Hallo Welt」、「Hola mundo」、「Salut le Monde」、「Ciao Mondo」の 5 つの挨拶のいずれかが表示されます。別のブラウザまたはシークレット モードでページを開くと、別の言語で表示されます。セッション データは Google Cloud Console で表示して編集できます。

    Cloud Console の Firestore セッション。

  4. HTTP サーバーを停止するには、ターミナル ウィンドウで Control+C を押します。

App Engine でのデプロイと実行

App Engine スタンダード環境を使用すると、高い負荷の下で大量のデータを使用して正常に動作するアプリをビルドしてデプロイできます。

このチュートリアルでは、App Engine スタンダード環境を使用してサーバーをデプロイします。

  1. ターミナル ウィンドウで app.yaml ファイルを作成し、以下をコピーします。

    runtime: python37
  2. App Engine にアプリをデプロイします。

    gcloud app deploy
    
  3. https://your-project-id.appspot.com で公開されているライブアプリを表示します。

    gcloud app browse
    

    ここで your-project-id は、Google Cloud プロジェクト ID です。

これで、App Engine インスタンスで実行しているウェブサーバーから挨拶が配信されます。

アプリのデバッグ

App Engine アプリに接続できない場合は、次の点を確認してください。

  1. gcloud デプロイ コマンドが正常に終了して、エラーを出力しなかったことを確認します。エラー(message=Build failed など)が発生した場合は、それらを修正してから、もう一度、App Engine アプリのデプロイを試みます。
  2. Cloud Console で、[ログビューア] ページに移動します。

    [ログビューア] ページに移動

    1. [最近選択したリソース] プルダウン リストで、[App Engine アプリケーション] をクリックしてから、[All module_id] をクリックします。アプリにアクセスした以降のリクエストのリストが表示されます。リクエストのリストが表示されない場合は、プルダウン リストで [All module_id ] が選択されていることを確認します。エラー メッセージが Cloud Console に出力された場合は、アプリのコードがウェブアプリの作成に関するセクション内のコードと一致することを確認します。

    2. Firestore API が有効になっていることを確認します。

クリーンアップ

プロジェクトの削除

  1. Cloud Console で [リソースの管理] ページに移動します。

    [リソースの管理] ページに移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

App Engine インスタンスの削除

  1. Cloud Console で、App Engine の [バージョン] ページに移動します。

    [バージョン] ページに移動

  2. デフォルト以外で削除するアプリのバージョンのチェックボックスをオンにします。
  3. [削除] をクリックして、アプリのバージョンを削除します。

次のステップ