

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 在版本 3 中使用 DynamoDB 会话处理程序 适用于 PHP 的 AWS SDK
<a name="service_dynamodb-session-handler"></a>

DynamoDB 会话处理程序是一个适用于 PHP 的自定义会话处理程序，让开发人员能够将 Amazon DynamoDB 用作会话存储。使用 DynamoDB 进行会话存储可将会话移离本地文件系统并将其移入共享位置，从而可减少在分布式 Web 应用程序中进行会话处理时出现的问题。DynamoDB 速度快、可扩展且易于部署，还能够自动处理数据复制。

DynamoDB 会话处理程序使用 `session_set_save_handler()` 函数将 DynamoDB 操作挂接到 PHP 的[本机会话函数](http://www.php.net/manual/en/ref.session.php)中，以允许简易替代。其中包括对会话锁定和垃圾回收等功能的支持，这些功能是 PHP 的默认会话处理程序的一部分。

有关 DynamoDB 服务的更多信息，请参阅 [Amazon DynamoDB 主页](https://aws.amazon.com/dynamodb/)。

## 基本用法
<a name="basic-usage"></a>

### 步骤 1：注册处理程序
<a name="step-1-register-the-handler"></a>

首先，实例化并注册会话处理程序。

```
use Aws\DynamoDb\SessionHandler;

$dynamoDb = new Aws\DynamoDb\DynamoDbClient([
    'region'=>'us-east-1'  // Since version 3.277.10 of the SDK, 
]);                        // the 'version' parameter defaults to 'latest'.

$sessionHandler = SessionHandler::fromClient($dynamoDb, [
    'table_name' => 'sessions'
]);

$sessionHandler->register();
```

### 步骤 2：创建用于存储会话的表
<a name="create-a-table-for-storing-your-sessions"></a>

在实际使用会话处理程序之前，您需要创建一个用于存储会话的表。通过使用[适用于 Amazon DynamoDB 的AWS 控制台](https://console.aws.amazon.com/dynamodb/home)或使用 适用于 PHP 的 AWS SDK，您可以提前完成此操作。

在创建此表时，请使用“id”作为主键的名称。此外，建议使用“expires”属性设置[“生存时间”属性](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html)以便从会话自动垃圾回收功能中受益。

### 步骤 3：像平常一样使用 PHP 会话
<a name="step-3-use-php-sessions-as-you-normally-would"></a>

一旦注册会话处理程序并且已存在表，您便可以像通常使用 PHP 的默认会话处理程序那样使用 `$_SESSION` 超级全局变量向会话读写内容。DynamoDB 会话处理程序会封装并提取与 DynamoDB 的交互，让您可以轻松地使用 PHP 的本机会话函数和接口。

```
// Start the session
session_start();

// Alter the session data
$_SESSION['user.name'] = 'jeremy';
$_SESSION['user.role'] = 'admin';

// Close the session (optional, but recommended)
session_write_close();
```

## 配置
<a name="configuration"></a>

您可以使用以下选项配置会话处理程序的行为。所有选项都是可选的，但务必要了解默认值为何值。

** `table_name` **  
存储会话的 DynamoDB 表的名称。默认值为 `'sessions'`。

** `hash_key` **  
DynamoDB 会话表中哈希键的名称。默认值为 `'id'`。

** `data_attribute` **  
DynamoDB 会话表中的属性名称，该会话表中存储了会话数据。默认值为 `'data'`。

** `data_attribute_type` **  
DynamoDB 会话表中属性的类型，该会话表中存储了会话数据。此项默认为 `'string'`，不过可以选择设置为 `'binary'`。

** `session_lifetime` **  
非活动会话在被垃圾回收之前的生命周期。如果未提供，将使用的实际生命周期值为 `ini_get('session.gc_maxlifetime')`。

** `session_lifetime_attribute` **  
DynamoDB 会话表中属性的名称，该会话表中存储了会话过期时间。默认值为 `'expires'`。

** `consistent_read` **  
会话处理程序是否应对 `GetItem` 操作使用一致性读取。默认值为 `true`。

** `locking` **  
是否使用会话锁定。默认值为 `false`。

** `batch_config` **  
用于在垃圾回收期间进行批量删除的配置。这些选项直接传递到 [DynamoDB 对象 WriteRequestBatch](https://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.DynamoDb.WriteRequestBatch.html)中。通过 `SessionHandler::garbageCollect()` 手动触发垃圾回收。

** `max_lock_wait_time` **  
会话处理程序在放弃之前应等待获取锁定的最长时间（以秒为单位）。默认值为 `10` 且只用于会话锁定。

** `min_lock_retry_microtime` **  
会话处理程序在两次获取锁定的尝试之间应等待的最短时间（以微秒为单位）。默认值为 `10000` 且只用于会话锁定。

** `max_lock_retry_microtime` **  
会话处理程序在两次获取锁定的尝试之间应等待的最长时间（以微秒为单位）。默认值为 `50000` 且只用于会话锁定。

要配置会话处理程序，请在实例化处理程序时指定配置选项。以下代码是已指定所有配置选项的示例。

```
$sessionHandler = SessionHandler::fromClient($dynamoDb, [
    'table_name'                    => 'sessions',
    'hash_key'                      => 'id',
    'data_attribute'                => 'data',
    'data_attribute_type'           => 'string',
    'session_lifetime'              => 3600,
    'session_lifetime_attribute'    => 'expires',
    'consistent_read'               => true,
    'locking'                       => false,
    'batch_config'                  => [],
    'max_lock_wait_time'            => 10,
    'min_lock_retry_microtime'      => 5000,
    'max_lock_retry_microtime'      => 50000,
]);
```

## 定价
<a name="pricing"></a>

除了数据存储和数据传输费用外，与使用 DynamoDB 相关的成本是根据表的预置的吞吐量容量来计算的（请参阅 [Amazon DynamoDB 定价详细信息](https://aws.amazon.com/dynamodb/pricing/)）。吞吐量用写入容量和读取容量单位来测量。Amazon DynamoDB 主页显示以下内容：

一个读取容量单位表示对大小为 4 KB 的项目每秒执行一次强一致性读取（或每秒执行两次最终一致性读取）。一个写入容量单位表示对大小为 1 KB 的项目每秒执行一次写入。

最后，吞吐量和会话表所需的成本将与您的预期流量和会话大小关联。下表说明了针对每个会话函数，对 DynamoDB 表执行的读取和写入操作量。


****  

|  |  | 
| --- |--- |
|  通过 `session_start()` 读取   |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/sdk-for-php/v3/developer-guide/service_dynamodb-session-handler.html)  | 
|  通过 `session_start()` 读取（使用会话锁定）  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/sdk-for-php/v3/developer-guide/service_dynamodb-session-handler.html)  | 
|  通过 `session_write_close()` 写入   |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/sdk-for-php/v3/developer-guide/service_dynamodb-session-handler.html)  | 
|  通过 `session_destroy()` 删除   |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/sdk-for-php/v3/developer-guide/service_dynamodb-session-handler.html)  | 
|  垃圾回收  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/sdk-for-php/v3/developer-guide/service_dynamodb-session-handler.html)  | 

## 会话锁定
<a name="ddbsh-session-locking"></a>

DynamoDB 会话处理程序支持保守的会话锁定，以模拟 PHP 的默认会话处理程序的行为。默认情况下，DynamoDB 会话处理程序会*关闭*此功能，因为它会成为性能瓶颈并增加成本，尤其是在应用程序使用 Ajax 请求或 iframe 来访问会话时。在启用该功能之前请认真考虑您的应用程序是否需要会话锁定。

要启用会话锁定，请在实例化 `'locking'` 时将 `true` 选项设置为 `SessionHandler`。

```
$sessionHandler = SessionHandler::fromClient($dynamoDb, [
    'table_name' => 'sessions',
    'locking'    => true,
]);
```

## 垃圾回收
<a name="ddbsh-garbage-collection"></a>

在您的 DynamoDB 表中使用属性“expires”设置 TTL 属性。这将自动对您的会话进行垃圾回收，从而无需自行对其进行垃圾回收。

或者，DynamoDB 会话处理程序通过使用一系列 `Scan` 和 `BatchWriteItem` 操作来支持会话垃圾回收。考虑到 `Scan` 操作的工作原理，为了找到所有过期会话并将其删除，垃圾回收过程可能需要大量预配置的吞吐量。

因此，我们不支持自动垃圾回收。更好的做法是将垃圾回收安排在非高峰时段进行，此时，突发吞吐量不会中断应用程序的剩余部分。例如，您可以有一个夜间 cron 作业触发器脚本，用于运行垃圾回收。此脚本需要执行类似如下的内容。

```
$sessionHandler = SessionHandler::fromClient($dynamoDb, [
    'table_name'   => 'sessions',
    'batch_config' => [
        'batch_size' => 25,
        'before' => function ($command) {
            echo "About to delete a batch of expired sessions.\n";
        }
    ]
]);

$sessionHandler->garbageCollect();
```

您还可以在 `'before'` 内使用 `'batch_config'` 选项，以便在垃圾回收流程所执行的 `BatchWriteItem` 操作之间引入延迟。这将增加完成垃圾回收所需的时间，但可以帮助您分散 DynamoDB 会话处理程序发出的请求，从而帮助您在垃圾回收期间接近预置的吞吐能力或保持在该容量内。

```
$sessionHandler = SessionHandler::fromClient($dynamoDb, [
    'table_name'   => 'sessions',
    'batch_config' => [
        'before' => function ($command) {
            $command['@http']['delay'] = 5000;
        }
    ]
]);

$sessionHandler->garbageCollect();
```

## 最佳实践
<a name="best-practices"></a>

1. 在地理位置最接近应用程序 AWS 服务器或与应用程序服务器位于同一区域的区域中创建会话表。这可以确保您的应用程序与 DynamoDB 数据库之间的延迟最低。

1. 认真选择您的会话表的预配的吞吐能力。考虑您的应用程序的预期流量和会话的预期大小。或者，对您的桌子使用 “按需” Read/Write 容量模式。

1. 通过 AWS 管理控制台或 Amazon 监控您消耗的吞吐量 CloudWatch，并根据需要调整吞吐量设置以满足应用程序的需求。

1. 使会话尽量小（最好小于 1 KB）。小型会话执行起来性能更好，需要的预置的吞吐能力更少。

1. 除非您的应用程序需要，否则请勿使用会话锁定。

1. 不使用 PHP 的内置会话垃圾回收触发器，而通过 cron 作业或其他计划机制将您的垃圾回收安排在非高峰时段运行。使用 `'batch_config'` 选项对您有利。

## 所需的 IAM 权限
<a name="required-iam-permissions"></a>

[要使用 Dynam SessionHhandler oDB，[您配置的凭证必须有权使用您在](guide_credentials.md)上一步中创建的 DynamoDB 表。](#create-a-table-for-storing-your-sessions)下面的 IAM policy 包含您需要的最低权限。要使用此策略，请将资源值替换为您之前创建的表的 Amazon 资源名称 (ARN)。有关创建和附加 IAM 策略的详细信息，请参阅 IAM 用户指南中的[管理 IAM 策略](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage.html)。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "SessionHandler",
            "Action": [
                "dynamodb:GetItem",
                "dynamodb:UpdateItem",
                "dynamodb:DeleteItem",
                "dynamodb:Scan",
                "dynamodb:BatchWriteItem"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/table-name"
        }
    ]
}
```

------