Amazon DynamoDB: Store PHP Sessions with Load Balancer

Share this article

This article is shared from one of our sister sites, CloudSpring. If you find it helpful, be sure to give them a visit!

This tutorial will show you how to use Amazon DynamoDB as a storage facility for PHP sessions. This method becomes very useful when your applications take advantage of the Elastic Load Balancing and Autoscaling services. You will need Amazon AWS account enabled to use EC2, Elastic Load Balancer and DynamoDB as a prerequisite to play along the tutorial.

What is an Elastic Load Balancer

Elastic Load Balancer acts as a front end for one or many of your virtual servers. It accepts requests and distributes them among virtual servers. Virtual servers can be created by cloning a machine template (AMI) or can be destroyed if needed. Processing power if your application can be varied by adding or reducing the virtual servers dynamically.

And Autoscaling?

When Autoscaling joins the game the system can also:
  • Start more clones of the web servers when there is high traffic
  • Shutdown some of them when the traffic drops below a predefined threshold
  • Terminate unhealthy instances and replace them if needed

How do I do it?

Can any of your applications work in this environment? Yes if it satisfies two critical requirements:
  • Since virtual servers are created dynamically, the servers should contain only the application code and not any data. This is easily doable with a DB service.
  • Any user session state should be persisted outside of virtual server. This is a little more tricky, because by default the PHP Module stores these data into che web server’s filesystem.
And this is the problem we’ll try to solve in this… uhm, session.

What not to do: sticky sessions

Sticky session is a feature of the Elastic Load Balancer service that binds a user’s session to a specific application instance, so that all requests coming from the user during the session will be sent to the same virtual server. The session cookie can be generated by either the load balancer or the application, but: this is considered a bad practice. The ideal thing would be to design the application as stateless, but this is not always possible.

Store your sessions in a database

Other option is: store our sessions inside a database. It could be the same external SQL database used by the application or a Memcache instance or another NoSQL database. In this case DynamoDB seems very interesting because it’s a powerful and fast NoSQL database, it’s managed by Amazon itself and is also easy accessible from our virtual servers. Also, AmazonDynamoDB class of the official PHP SDK is already equipped to register itself as session manager. If you never heard of DynamoDB I recommend you to watch this introductory video.

The demo application

I’ve put together a simple application to test the entire mechanism, you can download the source code from our Github repository. We will run this application using an elastic load balancer and at least two instances. We will not use autoscaling for now.

Welcome screen

The application asks the user to choose a username that is stored into the current session and acts as a “login”. If a username is present in the session the application allows the user to insert a kind of “profile”, essentially a series of key/value information such as name, last name, email etc (both key and value are strings). All this logic is included in the index.php
file.

The session.php file contains a simple Session library. This library allows us to manage session data with friendly methods such as $session->read('some_var') and $session->write('some_key', 'some_value'). This session object can be configured to use the default PHP session mechanism (if we are an a local testing server) or a custom class. The first step of our application file is session startup:
require_once 'lib/session.php';
try {
 // Engine can be PHP or AmazonDynamoDB
 $session = new Session($config['session']['engine'], $config['session']['params']);
} catch (Exception $e) {
 exit($e->getMessage());
} // end try
The default engine value is PHP which needs no parameters. If we choose the ‘AmazonDynamoDB’ engine, the session constructor will execute some additional code:
switch ($engine) {
case 'AmazonDynamoDB':
// Load AWS SDK
require_once 'AWSSDKforPHP/sdk.class.php';
// Create a list of credential sets that can be used with the SDK.
CFCredentials::set($params['credentials']);
// Instantiate a DynamoDB client
$dynamodb = new AmazonDynamoDB();
$dynamodb->set_region($params['region']);
// Instantiate, configure, and register the session handler
$this->handler = $dynamodb->register_session_handler(array(
'table_name'       => $params['table_name'],
'lifetime'         => $params['lifetime'],
));
break;
First we load the AWS SDK which must be already installed and reachable, then our credentials are loaded into the AWS environment. From this point on we can use AWS classes, so a new instance of AmazonDynamoDB is created and setup with the correct region where our table resides. Finally we tell our DynamoDB object to register himself as session manager passing the name of the table to use, and that’s really what we need. The config.php file is where we tell the application which engine we want to use, also our AWS credentials and DynamoDB settings are saved here. In the index.php I’ve also included a little utility function that, if we are not in the local server, fetches the name of the instance in which is currently running. This is useful to check that the session is kept consistent across our servers.
function getServerName() {
 $host = $_SERVER['SERVER_NAME'];
 if ('localhost' != $host) {
 // Maybe we are on EC2, trying to catch the current instance ID
 $ch = curl_init('http://169.254.169.254/latest/meta-data/instance-id');
 curl_setopt($ch, CURLOPT_FAILONERROR, true);
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
 if ($ret = curl_exec($ch)) {
 $host .= ' (instance ' . $ret . ')';
 } // end if
 curl_close($ch);
 } // end if
 return $host;
} // end function
The function getServerName() uses the EC2 Metadata API to find the instance’s name. Run the app on your fleet In order to test this application we need a fleet of at least two web servers behind a load balancer. The server I used is an Ubuntu GNU/Linux instance equipped with:
  • the Apache web server,
  • PHP 5.3 (both command line and apache module),
  • the cURL program and PHP extension,
  • the Pear package manager (needed to install the SDK easily),
  • the AWS SDK for PHP (I suggest the installation by Pear).
If you know how to build an AMI, you can build yours from scratch. But you can also use the one I’ve prepared and made public: ami-4b42443f. This machine already contains the PHP source code for the application and all the other dependencies. Once you have your AMI ready… let’s go!

Initialize the session storage

Go to your AWS console, select the DynamoDB service and your favorite region (mine is EU West – Ireland). Click on the “Create Table” button.

Create the table, step 1

Enter “test_sessions” as table name and chose a string primary key called “id”, the key type must be “hash”. If you choose another name it must be copied in the config.php file later. Enter “10” for both the read and write capacity units fields (eg. how fast is your table), this is enough to test.

Create the table, step 2

Now you have a NoSQL table where each row have a mandatory id field but can have a variable number of other different fields of type string, number, string set or number set. The session manager object will use a string field named “data” to store the session’s variables and a number field named “expires” for the expiration timestamp of the session.

Launch and configure the servers

Choose the AMI to launch

Now select the EC2 service and the same region you chose for the DynamoDB table. Click on the “Launch Instance” button from either the Dashboard or the “Instances” section. Select your custom AMI or, with the classic wizard, go to the “Community AMIs” tab and enter “ami–4b42443f”. In the next screen enter at least “2” for the number of instances and choose your instance type, I chose Micro (t1.micro). You can leave “no preference” in the availability zone dropdown, but in a production environment it’s better if the various instances are distributed between two or more zones inside the same region. Accept the default settings for both the “Instance Details” and the “Storage Device” configuration panels, then continue. Enter one or more optional tags if you want. Choose a keypair or create a new one and choose a security group which allows at least HTTP on port 80 and SSH on port 22.

Instance settings recap

Review your settings then launch the instances. When the instances state is “running” they can be configured via SSH. Each instance has a public DNS name similar to ec2-xxx-xxx-xx-xx.region.compute.amazonaws.com. You’ll need to edit the config.php file on each instance you created. Connect to the instance with SSH or with an SFTP client using your public key and the username “ubuntu” (if you used my public AMI): $ ssh -i /path/to/key.pem ubuntu@ec2-X-X-X-X.region.compute.amazonaws.com Change the current directory to /var/www where the test application is located. Edit the config.php file inserting your AWS key and secret. Then check if your DynamoDB table settings matches, you will surely have to edit the region with the appropriate value that can be found in this reference. Then create an empty file called ping.html inside /var/www: this file will be used by the load balancer to test the reachability of each instance.

Setting up the load balancer

With the database and all the instances in place we can now setup the frontend load balancer. In the EC2 navigation menu, under “Network & Security” choose “Load Balancers” and click on the “Create Load Balancer” button.

Load balancer creation screen

Choose a name for the load balancer and verify that the listener configuration matches that of the screenshot, that basically says: forward all the HTTP traffic on port 80 of the load balancer to HTTP on port 80 of the instances.

Load balancer health settings

In the health check panel enter /ping.html in the ping path field and leave the other settings as default. This means: call the /ping.html resource of each instance every 30 seconds, if the response time is longer then 5 seconds the check fails, if the instance fails two consecutive health checks it’s unhealthy, if it passes 10 consecutive checks the instance is healthy. The load balancer will not forward traffic to an unhealthy instance and if autoscale is in place the unhealthy instances can be terminated and replaced by new fresh ones.

Attach instances

The next screen lets you choose which of the currently running instances can be added to the load balancer. Select the two instances created previously and go on. Review the final configuration and confirm if it’s ok for you. Now, you should be able to see the load balancer’s details and the status of all the connected instances.

ELB recap screen

You can test the application by putting the load balancer’s DNS name (something like yourname-12345678.region.elb.amazonaws.com) into a browser. You can also configure a domain or subdomain (eg. dynamo.yourdomain.com) by adding a CNAME in your DNS panel that points to the load balancer URL. It’s not recommended to use the IP with an A record because the IP can change overtime.

Screenshot comparison

Each time you submit the form or refresh the page you request can be processed by a different instance. You can check which instance is serving you by the name displayed through the getServerName() utility.

Summary

And that’s all for now. We’ve covered an important topic in the AWS ecosystem, but this is just the beginning. All this stuff is entirely programmable, for example: you can add autoscaling and design your instances to be self-configurable and download AWS credentials and other data from a trusted place. Or you can use Cloud Formation to create a reusable template for the entire infrastructure. The starting point to check is the AWS Homepage. And now if you’ve finished testing don’t forget to terminate all your stuff, if not Happy Coding! Image via Fotolia

Frequently Asked Questions (FAQs) on Amazon DynamoDB and PHP Sessions

How Can I Implement Load Balancing with Amazon DynamoDB and PHP Sessions?

Load balancing is a crucial aspect of managing server load and ensuring optimal performance. With Amazon DynamoDB and PHP sessions, you can achieve this by using Amazon’s Elastic Load Balancing (ELB) service. ELB automatically distributes incoming application traffic across multiple targets, such as Amazon EC2 instances, containers, and IP addresses. It can handle the varying load of your application traffic in a single Availability Zone or across multiple Availability Zones.

What are the Benefits of Using Amazon DynamoDB for PHP Sessions?

Amazon DynamoDB offers several benefits for PHP sessions. It provides fast and predictable performance with seamless scalability. You can scale your tables up or down to adjust for traffic, without any downtime or performance degradation. DynamoDB also offers built-in security, backup and restore, and in-memory caching for internet-scale applications.

How Can I Use the AWS SDK for PHP with DynamoDB?

The AWS SDK for PHP makes it easier for developers to build applications that tap into the cost-effective, scalable, and reliable AWS cloud. Included in the SDK are the AWS PHP Library and code samples that show how to use the AWS SDK for PHP to tap into all of the functionality provided by AWS services like Amazon S3, Amazon EC2, and DynamoDB.

What are Some Common DynamoDB with PHP Code Examples?

There are several common code examples for using DynamoDB with PHP. These include creating a table, writing items to a table, reading items from a table, updating items in a table, and deleting items from a table. Each of these operations can be performed using the AWS SDK for PHP.

Where Can I Find PHP Scripts for Amazon Store?

You can find PHP scripts for Amazon Store on various online platforms like CodeCanyon. These scripts allow you to integrate Amazon’s services into your PHP applications, providing functionality like product search and display, shopping cart management, and order processing.

Are There Complete Examples for DynamoDB with PHP?

Yes, there are complete examples for using DynamoDB with PHP. These examples typically include code for creating a table, writing items to the table, reading items from the table, updating items in the table, and deleting items from the table. They also often include examples of how to handle errors and exceptions.

How Can I Handle Errors and Exceptions in DynamoDB with PHP?

When working with DynamoDB and PHP, you can handle errors and exceptions using try-catch blocks. The AWS SDK for PHP throws exceptions when operations fail, and you can catch these exceptions to handle them in a way that suits your application.

How Can I Optimize Performance with DynamoDB and PHP?

There are several ways to optimize performance with DynamoDB and PHP. These include using provisioned throughput to manage capacity, using global secondary indexes to speed up queries, and using DynamoDB Accelerator (DAX) to provide in-memory caching.

How Can I Secure My Data in DynamoDB?

DynamoDB provides several security features to protect your data. These include encryption at rest, which secures your data from unauthorized access to the underlying storage, and encryption in transit, which protects your data as it travels between your application and DynamoDB.

How Can I Backup and Restore Data in DynamoDB?

DynamoDB provides built-in support for data backup and restore. You can create on-demand backups at any time, and restore your table data from these backups when needed. This allows you to protect your data from accidental deletion or modification, and to keep your application running smoothly even in the event of a failure.

Vito TardiaVito Tardia
View Author

Vito Tardia (a.k.a. Ragman), is a web designer and full stack developer with 20+ years experience. He builds websites and applications in London, UK. Vito is also a skilled guitarist and music composer and enjoys writing music and jamming with local (hard) rock bands. In 2019 he started the BlueMelt instrumental guitar rock project.

Advanced
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week