Одной из проблем при создании распределенного веб-приложения является обработка сессий. Если у вас запущено несколько экземпляров приложения, а данные сеанса записываются в локальные файлы (как это происходит по умолчанию для функций обработки сеансов в 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 в качестве хранилища сеансов. Если у вас есть мнение по этому поводу, пожалуйста, дайте мне знать в комментариях.