サーバー側セッションキャッシングの背後にある基本的な考え方を理解するために、Python でのウェブ開発用のマイクロフレームワークである Flask を使用した小さなアプリケーションを実装します。特定のフレームワークと言語の詳細ではなく概念に焦点を当てているため、選択したウェブフレームワークとプログラミング言語に例を翻訳できます。

Flask を使い始める場合は、インストール手順クイックスタートガイド通りに動作を行ってください。

以下は、ログインとログアウトを可能にする基本的なアプリケーションです。

構文: python

import os
from flask import Flask, session, redirect, escape, request

app = Flask(__name__)
app.secret_key = os.environ.get('SECRET_KEY', default=None)

@app.route('/')

def index():

    if 'username' in session:
        return 'Logged in as %s' % escape(session['username'])

    return 'You are not logged in'

@app.route('/login', methods=['GET', 'POST'])

def login():

    if request.method == 'POST':

        session['username'] = request.form['username']
        return redirect('/')

    return '''
        <form method="post">
        <p><input type=text name=username>
        <p><input type=submit value=Login>
        </form>
    '''

@app.route('/logout')

def logout():

    session.pop('username', None)
    return redirect('/')

残りの例は、このスニペットに基づいています。すべての例のコードは、このリポジトリにあります。

Flask がインストールされている状態でこのアプリを起動する場合は、example-1.py というファイルにコードをコピーします。次に、2 つの環境変数をエクスポートする必要があります。FLASK_APP を example-1.py に設定し、SECRET_KEY をランダムな文字列 (Y0PJWblKsg1axM4fGW など) に設定する必要があります。環境変数の設定についてサポートが必要な場合は、Flask のクイックスタートガイドを確認してください。

すべての設定が完了したら、次のコマンドを実行します。

構文: シェル

$ flask run -h 0.0.0.0 -p 5000 --reload

次に、http://your_flask_endpoint:5000 に移動します。ここで、アプリが実行されていることを確認します。要件で行ったように、your_flask_endpoint を EC2 インスタンスのパブリック DNS 名に置き換える必要があります。

「/」、「/login」、「/logout」の 3 つのルートを使用できます。すべてを順番通りにアクセスすると、基本的な動作に慣れることができます。

モジュールの所要時間: 60~90 分


この例では、クッキーを使用してユーザー名を保存しています。最初にアプリケーションにアクセスしたとき、セッションオブジェクトに保存されているユーザー名はありません。「/login」に移動してユーザー名を指定すると、値は署名付きクッキーに保存され、ホームページにリダイレクトされます。次に、「/logout」に移動すると、ユーザー名がセッションから削除され、元の場所に戻ります。

この基本的なアプリケーションをサーバー側セッションで拡張します。ただし、最初に Redis に接続できることを確認します。



ステップ 2.1

(クリックして拡大)

ステップ 2.1

例では、Redis エンドポイントが言及されるたびに、プライマリエンドポイントのホスト名を使用する必要があります。 

ステップ 2.2

(クリックして拡大)

ステップ 2.2

構文: シェル

$ export REDIS_URL="redis://your_redis_endpoint:6379"

構文: シェル

$ python

構文: python

>>> import redis
>>> client = redis.Redis.from_url('redis://your_redis_endpoint:6379')
>>> client.ping()

**True**

切断された場合は、セキュリティグループの設定によってブロックされていることを意味します。EC2 インスタンスが、ElastiCache インスタンスに割り当てられたセキュリティグループにアクセスできることを確認します。たとえば、EC2 インスタンスがデフォルトのセキュリティグループに割り当てられていたとします。Amazon ElastiCache インスタンスのセキュリティグループを変更し、デフォルトのセキュリティグループ内のインスタンスからポート 6379 での接続を許可するカスタム TCP ルールを追加できます。 

ステップ 2.5

ソースでは、セキュリティグループ名の入力を開始し、セキュリティグループ ID をクリックできるようになります。セキュリティグループの詳細を確認する必要がある場合は、ドキュメントまたはセキュリティグループルールのリファレンスをご確認ください。


例に戻りましょう。ここで、セッションデータを Redis に保存できるようにする小さな変更をいくつか紹介します。これらの変更を加えた 2 番目の例を次に示します。

構文: python

import os
import redis
from flask import Flask, session, redirect, escape, request

app = Flask(__name__)

app.secret_key = os.environ.get('SECRET_KEY', default=None)

# BEGIN NEW CODE - PART 1 #
REDIS_URL = os.environ.get('REDIS_URL')
store = redis.Redis.from_url(REDIS_URL)
# END NEW CODE - PART 1 #

@app.route('/')

def index():

    if 'username' in session:

        # BEGIN NEW CODE - PART 2 #
        username = escape(session['username'])
        visits = store.hincrby(username, 'visits', 1)

    return '''
        Logged in as {0}.<br>
        Visits: {1}
        '''.format(username, visits)
        # END NEW CODE - PART 2 #

    return 'You are not logged in'

@app.route('/login', methods=['GET', 'POST'])

def login():

    if request.method == 'POST':
        session['username'] = request.form['username']
        return redirect('/')

    return '''
        <form method="post">
        <p><input type=text name=username>
        <p><input type=submit value=Login>
        </form>'''

@app.route('/logout')

def logout():

    session.pop('username', None)
    return redirect('/')

これで Redis がインポートおよび初期化され、インデックスがカウンターを増分してユーザーに表示します。

カウンターを増分するために使用した Redis コマンドは HINCRBY です。各ユーザーのセッションに Redis ハッシュを使用しているのが、その理由です。


次に、サーバー側セッションに有効期限 (TTL) を設定します。コードを 1 行追加しただけで、このスニペットには / ルートのみが含まれます。

構文: python

...
@app.route('/')

def index():

    if 'username' in session:

        username = escape(session['username'])
        visits = store.hincrby(username, 'visits', 1)
        # BEGIN NEW CODE #
        store.expire(username, 10)
        # END NEW CODE #

        return '''
            Logged in as {0}.<br>
            Visits: {1}
            '''.format(username, visits)

    return 'You are not logged in'
...

セッションが保存されているキーは 10 秒で期限切れになります。これは非常に短い TTL であるため、この例でのみ役立ちます。ここでアプリケーションを実行した場合、インデックスにアクセスすると訪問カウンターが更新される仕組みがわかります。ただし、そのページにアクセスせずに 10 秒経過すると、次の更新時にカウンターが 1 に戻ります。


この短い例でもサーバー側セッションの基本を学習するには十分ですが、実際のシナリオでは別の動作を行います。ユーザー名を保存する代わりに、ユーザーが認証されるとトークンを生成して保存します。そのトークンは、すべてのサーバー側セッションデータが保存される Redis キーを表します。また、ここに示されている動作の一部を抽象化して、サーバー側セッションへのアクセスが、介入なしで TTL を更新するように設定することもできます。リポジトリには、その動作を抽象化する SessionStore クラスを提供する例があります。