Статьи

Обработка PHP-сессий в Windows Azure

Одной из проблем при создании распределенного веб-приложения является обработка сессий. Если у вас запущено несколько экземпляров приложения, а данные сеанса записываются в локальные файлы (как это происходит по умолчанию для функций обработки сеансов в PHP ), сеанс пользователя может быть потерян, если сеанс запущен в одном экземпляре, но последующие запросы направлены (через балансировщик нагрузки) в другие экземпляры. Чтобы успешно управлять сеансами в нескольких экземплярах, вам нужно общее хранилище данных. В этой статье я покажу вам, как Windows Azure SDK для PHP облегчает эту задачу, сохраняя данные сеансов в хранилище таблиц Windows Azure .

В версии 4.0 Windows Azure SDK для PHP обработка сеанса с помощью Windows Azure Table и хранилища BLOB-объектов была включена в недавно добавленный класс SessionHandler .

Примечание . Класс SessionHandler поддерживает хранение данных сеанса в хранилище таблиц или хранилище BLOB-объектов . Я сосредоточусь на использовании хранилища таблиц в этом посте в основном потому, что мне не удалось придумать сценарий, в котором использование хранилища BLOB-объектов было бы лучше (или даже необходимо). Если у вас есть идеи о том, как / почему хранилище BLOB-объектов было бы лучше, я бы хотел их услышать.

Класс SessionHandler позволяет писать код для обработки сеансов так же, как вы всегда это делаете, но данные сеансов хранятся в таблице Windows Azure, а не в локальных файлах. Для этого перед обычным кодом обработки сеанса добавьте следующие строки:

    require_once 'Microsoft/WindowsAzure/Storage/Table.php';
    require_once 'Microsoft/WindowsAzure/SessionHandler.php';
    $storageClient = new Microsoft_WindowsAzure_Storage_Table('table.core.windows.net', 
                                                              'your storage account name', 
                                                              'your storage account key');
    $sessionHandler = new Microsoft_WindowsAzure_SessionHandler($storageClient , 'sessionstable');
    $sessionHandler->register();

Теперь вы можете вызывать session_start () и другие функции сеанса, как обычно. Хорошо, это просто работает.

На самом деле, это все , что есть в использовании в SessionHandler , но я нашел , что это интересно взглянуть на , как это работает. Первая интересная вещь, которую нужно отметить, это то, что метод register просто вызывает функцию session_set_save_handler, чтобы по существу отобразить функциональность обработки сеанса в пользовательские функции. Вот как выглядит метод из исходного кода:

    public function register()
    {
        return session_set_save_handler(array($this, 'open'),
                                        array($this, 'close'),
                                        array($this, 'read'),
                                        array($this, 'write'),
                                        array($this, 'destroy'),
                                        array($this, 'gc')
        );
    }

Чтение, запись и удаление данных сеанса немного сложнее. При записи данных сеанса пары ключ-значение, составляющие данные, сначала сериализуются, а затем кодируются в base64 . Сериализация данных обеспечивает большую гибкость в данных, которые вы хотите сохранить (т.е. вам не нужно беспокоиться о соответствии какой-либо схемы в хранилище данных). При хранении данных в таблице каждая запись должна иметь ключ раздела и ключ строки, которые однозначно идентифицируют ее. Ключ раздела — это строка (по умолчанию «session», но она может изменяться в конструкторе класса), а ключ строки — это идентификатор сессии. (Для получения дополнительной информации о структуре таблиц, см этоpost.) Наконец, данные либо обновляются (если они уже существуют в таблице), либо вставляется новая запись. Вот часть функции записи:

$serializedData = base64_encode(serialize($serializedData));
 
$sessionRecord = new Microsoft_WindowsAzure_Storage_DynamicTableEntity($this->_sessionContainerPartition, $id);
$sessionRecord->sessionExpires = time();
$sessionRecord->serializedData = $serializedData;
 
try
{
    $this->_storage->updateEntity($this->_sessionContainer, $sessionRecord);
}
catch (Microsoft_WindowsAzure_Exception $unknownRecord)
{
    $this->_storage->insertEntity($this->_sessionContainer, $sessionRecord);
}

Неудивительно, что когда данные сеанса считываются из таблицы, они извлекаются по идентификатору сеанса, декодируются в base64 и не сериализуются. Опять же, вот фрагмент, который показывает, что происходит:

    $sessionRecord = $this->_storage->retrieveEntityById(
        $this->_sessionContainer,
        $this->_sessionContainerPartition,
        $id
    );
    return unserialize(base64_decode($sessionRecord->serializedData));

Как видите, класс SessionHandler хорошо использует API хранилища в SDK. Чтобы узнать больше о классе SessionHandler (и API хранилища), ознакомьтесь с документацией по Codeplex . Вы можете, конечно, получить полный исходный код здесь: http://phpazure.codeplex.com/SourceControl/list/changesets .

Исследуя обработку сеансов в Windows Azure SDK для PHP, я заметил, что отсутствие поддержки SQL Azure как хранилища сеансов было заметно. Мне интересно, сколько людей предпочли бы использовать SQL Azure вместо таблиц Azure в качестве хранилища сеансов. Если у вас есть мнение по этому поводу, пожалуйста, дайте мне знать в комментариях.