Handling PHP Sessions in Windows Azure
One of the challenges in building a distributed web application is in handling sessions. When you have multiple instances of an application running and session data is written to local files (as is the default behavior for the session handling functions in PHP) a user session can be lost when a session is started on one instance but subsequent requests are directed (via a load balancer) to other instances. To successfully manage sessions across multiple instances, you need a common data store. In this post I’ll show you how the Windows Azure SDK for PHP makes this easy by storing session data in Windows Azure Table storage.
In the 4.0 release of the Windows Azure SDK for PHP, session handling via Windows Azure Table and Blob storage was included in the newly added SessionHandler class.
Note: The SessionHandler class supports storing session data in Table storage or Blob storage. I will focus on using Table storage in this post largely because I haven’t been able to come up with a scenario in which using Blob storage would be better (or even necessary). If you have ideas about how/why Blob storage would be better, I’d love to hear them.
The SessionHandler class makes it possible to write code for handling sessions in the same way you always have, but the session data is stored on a Windows Azure Table instead of local files. To accomplish this, precede your usual session handling code with these lines:
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();
Now you can call session_start() and other session functions as you normally would. Nicely, it just works.
Really, that’s all there is to using the SessionHandler, but I found it interesting to take a look at how it works. The first interesting thing to note is that the register method is simply calling the session_set_save_handler function to essentially map the session handling functionality to custom functions. Here’s what the method looks like from the source code:
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') ); }
The reading, writing, and deleting of session data is only slightly more complicated. When writing session data, the key-value pairs that make up the data are first serialized and then base64 encoded. The serialization of the data allows for lots of flexibility in the data you want to store (i.e. you don’t have to worry about matching some schema in the data store). When storing data in a table, each entry must have a partition key and row key that uniquely identify it. The partition key is a string (“sessions” by default, but this is changeable in the class constructor) and the the row key is the session ID. (For more information about the structure of Tables, see this post.) Finally, the data is either updated (it it already exists in the Table) or a new entry is inserted. Here’s a portion of the write function:
$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); }
Not surprisingly, when session data is read from the table, it is retrieved by session ID, base64 decoded, and unserialized. Again, here’s a snippet that show’s what is happening:
$sessionRecord = $this->_storage->retrieveEntityById( $this->_sessionContainer, $this->_sessionContainerPartition, $id ); return unserialize(base64_decode($sessionRecord->serializedData));
As you can see, the SessionHandler class makes good use of the storage APIs in the SDK. To learn more about the SessionHandler class (and the storage APIs), check out the documentation on Codeplex. You can, of course, get the complete source code here: https://phpazure.codeplex.com/SourceControl/list/changesets.
As I investigated the session handling in the Windows Azure SDK for PHP, I noticed that the absence of support for SQL Azure as a session store was conspicuous. I’m curious about how many people would prefer to use SQL Azure over Azure Tables as a session store. If you have an opinion on this, please let me know in the comments.
Thanks.
-Brian
Comments
Anonymous
January 09, 2012
Hi Brain, nice article. I had the experince that the table storage session handler slows down my application about more than 300ms. Have you noticed the same issue? On the other hand I was trying to use SQL Azure as session storage but the symfony plugin I found does not really work with MSSQL/SQL Azure :( So I'm also looking forward for a faster solution from codeplex.Anonymous
January 10, 2012
I haven't run any perf tests...but I will now. :-)Anonymous
January 17, 2012
I know wrote my own SQLAzureSessionHandler (for symfony 1.4). It's >50% faster than table storage handler. The only con is the session size. SQLAzure 8kB, TableStorage 64kB.Anonymous
January 24, 2012
@tbaumann- I've found table storage to be blazing fast if I use batching for inserts (blog post coming). -BrianAnonymous
October 01, 2014
Hello Brian - I realize this is an old post, but Microsoft_WindowsAzure_SessionHandler appears to have been depreciated with no direct replacement. Any chance you post an update on the current strategies for handling PHP sessions? Thanks!Anonymous
October 02, 2014
There is a new contrib project which provides a PHP Session Handler for Azure Table Storage, it is available on GitHub. github.com/.../azure-session-handlerAnonymous
October 22, 2014
Thanks SyntaxC4 - Are you aware of any documentation for the azure-session-handler on GitHub? I've installed via Composer, and found some old documentation, but cannot get it running.Anonymous
July 05, 2015
Amazing workAnonymous
July 05, 2015
Good one