DynamoDB セッションハンドラー
Aws.DynamoDbSession は、Aws\DynamoDb\SessionHandler を使ってセッションを DynamoDB のテーブルに 保存します。config/core.php (レガシー構成では app/Config/core.php) で設定します。
Configure::write('Session', [
'defaults' => 'php',
'cookie' => 'MY_APP',
'handler' => [
'engine' => 'Aws.DynamoDbSession',
'table_name' => 'DYNAMODB_TABLE_NAME',
// Optional: other options of Aws\DynamoDb\SessionHandler (default: 'locking' => true)
// 'locking' => true,
],
// Minutes; also the lifetime written to the "expires" attribute of each item
'timeout' => 1440,
'ini' => [
'session.cookie_lifetime' => 0,
// Expired sessions are removed by DynamoDB's Time to Live, not by PHP's garbage collection
'session.gc_probability' => 0,
],
]);handler.table_nameは必須です。指定がない場合はCakeExceptionが投げられます。handlerのほかのキー (engineを除く) は、SDK のセッションハンドラーに渡されます。たとえばlocking、session_lifetime、consistent_readです。'locking' => falseを設定しない限り、 セッションのロックは有効です。session_lifetimeは、セッションが期限切れになるまでの秒数です。デフォルトはSession.timeoutの分数、 つまりCakeSessionがチェックするタイムアウトなので、セッションのアイテムはセッションと同時に 期限切れになります。Session.timeoutがない場合のデフォルトはsession.gc_maxlifetimeです。- テーブルは、
idという名前の文字列型のパーティションキーを持つ状態で存在している必要があり、expires属性で Time to Live が有効になっていなければなりません (セッションテーブルの作成 をご覧ください)。 - DynamoDB クライアントは
Awsの設定で作成されます。そのため、セッションが開始される前に プラグインを読み込み、Awsを設定しておく必要があります。 - 複数のアプリケーションでドメインとテーブルを共有する場合は、互いのセッションを読み込まないように、 アプリケーションごとに別のセッション Cookie 名 (
Session.cookie) を付けてください。
アイテムは AWS SDK のセッションハンドラーのものと同じです。キーは <session name>_<session id>、 データは文字列、有効期限は expires に入る Unix タイムスタンプで、lock 属性はロックされた セッションを示します。pieceofcake2/async-aws も同じアイテムを書き込むので、両方のプラグインで同じ テーブルを使えます。
セッションテーブルの作成
AWS CLI でテーブルを作成し、expires 属性で Time to Live を有効にします。
aws dynamodb create-table --table-name DYNAMODB_TABLE_NAME \
--attribute-definitions AttributeName=id,AttributeType=S \
--key-schema AttributeName=id,KeyType=HASH \
--billing-mode PAY_PER_REQUEST
aws dynamodb update-time-to-live --table-name DYNAMODB_TABLE_NAME \
--time-to-live-specification "Enabled=true,AttributeName=expires"セッションの有効期限切れ
期限切れのセッションは DynamoDB 自身が削除します。
- セッションを書き込んだり閉じたりするたびに、その有効期限 (現在時刻に
session_lifetimeを 足したもの) がexpires属性に保存されます。 - DynamoDB の Time to Live が、
expiresの時刻を過ぎたアイテムを削除します。これはバックグラウンドで無料で実行されますが、 すぐには削除されません。期限切れのアイテムは最大で約 48 時間、場合によってはそれ以上テーブルに 残ることがあります。 - それまでの間、ハンドラーは期限切れのセッションを削除せずに空のセッションとして読み込み、次にその セッションを書き込むときに古いデータを置き換えます。期限切れのセッションが復活することはありません。
PHP のセッションのガベージコレクションはオフです。例では session.gc_probability を 0 にしています。 また、Session.ini に session.gc_probability が含まれていない場合も、DynamoDbSession がこれを 0 に設定します。
ガベージコレクション
Time to Live を使わないテーブルのために、DynamoDbSession::gc() で期限切れのセッションを削除することも できます。gc() はテーブル全体をスキャンして expires の時刻を過ぎたアイテムを探し、BatchWriteItem で削除します (1 リクエストあたり 25 アイテムで、未処理のアイテムは数回リトライします)。エラーは session スコープでログに記録され、リクエストを中断することはありません。
スキャンはテーブルのすべてのアイテムを読み込み、その分の料金がかかります。また、PHP が ガベージコレクションに選んだリクエストの中で実行されます。そのため、Time to Live が有効な場合は オフのままにしてください。オンにするには、Session.ini で確率を設定します。たとえば、セッション開始 1000 回に 1 回の場合は次のようにします。
Configure::write('Session', [
// ...
'ini' => [
'session.cookie_lifetime' => 0,
'session.gc_probability' => 1,
'session.gc_divisor' => 1000,
],
]);SDK の SessionHandler::garbageCollect() も同じ方法で削除します。
DynamoDB Local
DynamoDB Local は Time to Live の設定を受け付けますが、期限切れのアイテムを削除するかどうかはバージョンによります (現在の amazon/dynamodb-local イメージは削除します)。期限切れのセッションは常に空として読み込まれます。 テーブルに残る場合は、手動で削除するか、ローカルの開発環境では上記のようにガベージコレクションを オンにしてください。
SDK のセッションハンドラーは Action を指定せずに UpdateItem リクエストを送信し、DynamoDB の デフォルトである PUT に頼っていますが、DynamoDB Local はこのデフォルトを適用しません。 DynamoDbSession はこれらのリクエストに 'Action' => 'PUT' を追加するので、DynamoDB Local にも セッションが保存されます。
