All this cannot be served without managing web sessions linking feature data to a particular visitor's web browser.
Usually this session data is stored in the web application' s memory or on disks. With more and more visitors adding load the solution is distributed to more servers. The solution becomes finally more complex using load balancers with sticky connections to compensate for the non distributed session information and replicating session data among web servers to achieve more availability.
A central database for session persistence often adds another failure point to the architecture or rarely delivers the performance at a reasonable cost level.
This text describes a low cost session management solution base on MySQL Cluster Database allowing a simple but high available architecture. MySQL Cluster serves as a central session storage running on multiple computers. Data within this Cluster is automatically distributed, load balanced and replicated to deliver the necessary performance and high availability.
Cluster can be accessed using MySQL Server maintaining. The architecture has proven to easily accommodate the web session management of thousands of concurrent visitors using a low price standard of the shelf hardware.
Hypertext Transfer Protocol (HTTP) as protocol between the browser and the web server is stateless. The protocol requires no permanent connection between the browser as a client and the web server. A HTTP transaction is complete by the browser sending a request to the web server and the response as a reply.
There is no persistence of a connection to the next request. In addition no requirements have been defined for any browser to identify itself for a single request.
Because all web based services relies on HTTP for communication, maintaining state in a web application is an additional challenge.
|
Both methods require the identification of client. Several methods exist to transfer the client's browser state or identity. The state can be stored on client or server side:
Cookies are an extension of HTTP that were introduced to help provide stateful HTTP transactions. Cookies can be used to identify a single browser for recurring HTTP transactions or to store state information. States can also be passed in the URL, but accidental disclosure of this information poses serious security risks.
Please also note that URL rewriting is a solution and even a must when handling WAP sessions.
session_start()
.
Session variables are stored in the $_SESSION[]
array.
Session contents are stored on script termination and restored on
consecutive session_start()
calls. Most aspects of PHP session
handling are still configurable.
|
PHPSESSID
(settable using session_name()
).
The default session ID is a MD5 checksum based on
date, time, the client IP and other request data
(settable using session_id()
).
Transparent session ID rewriting can take care of adding
the session ID to URLs in absence of cookies.
PHP sessions are persistent by design. PHP has a sessions
module available. A "pluggable" database support exists
(the default file persistence is build in) but manual programming required.
The respective session management module will be simply loaded by the a
function call to session_module_name (
Using the PHP build-in session file based sessions a file will be
created in the configured path. The file name contains the
session ID.
Session variable contents are stored in serialized (text) format:
or in a more compact binary format. Customization of session
storage is possible from within PHP extensions or
PHP userland code.
In the recommended and most common solution the data column
will hold the session data in the same serialized format as it is used
in the file based session storage.
Please note that the ENGINE clause is only available in MySQL. Using
other databases you have to omit this keyword. If you intend to use
MySQL you should use a storage engine allowing row level locking
(such as InnoDB or Cluster like discussed later on).
A load balancer or virtual server is necessary to distribute the
HTTP requests to the differernt web servers. Local storage of
session data requires forwarding of
same client request to always same server
A usual way to "balance" distributed load is partitioning. Very often an algrithm is
used on the session id to equaly distribute sessions to different servers. Each
session will then be routed to a dedicated server with a local storage.
Unfortunately this will require "sticky connections" since partitioning is made
strickly by web users and a local web server storage is used. Session data
can not be shared among different web servers. Each user is then routed to a dedicated
web server. This will introduce new problems even if several
server can share the load now. E.g. "bleeding techniques" are needed to
move new users to a new server over a longer period of time just to shut down
a single server for maintenance.
Even if it is a single point of failure the session data is
at least still available if a system goes off-line.
as MySQL Cluster meets all of our requirements for a session
storage table:
count|i:5;foo|s:3:"bar";
PHP Custom Session Handlers
A user defined session handler has to implement the following functions:
open()
- open/lock session storageclose()
- close/unlock session storageread()
- read stored serialized datawrite()
- store serialized session datadestroy()
- delete session datagc()
- remove expired sessionsPHP SQL Session Storage
In order to store session data in a MySQL database we
need a table like this:
CREATE TABLE `test`.`session` (
`id` CHAR(32) PRIMARY KEY,
`data` TEXT,
`usetime` TIMESTAMP ,
) ENGINE=<...>
PHP Session Handler functions
The following code will implement the full session management API needed
to run session management in a (My)SQL database.
$_my_dbh = NULL;
function my_open($path, $name)
{
global $_my_dbh;
$_my_dbh = mysql_connect("localhost", "root", "");
mysql_select_db("test", $_my_dbh);
mysql_query("BEGIN TRANSACTION", $my_dbh);
}
function my_close()
{
global $my_dbh;
mysql_close($my_dbh);
}
function my_read($id)
{
global $my_dbh;
$res = mysql_query(
"SELECT data FROM session WHERE id='$id' FOR UPDATE", $my_dbh);
$row = mysql_fetch_assoc($res);
mysql_free_result($res);
if (is_array($row))
return $row['data'];
return "";
}
function my_write($id, $data)
{
global $my_dbh;
$data = mysql_escape_string($data);
mysql_query("INSERT INTO session (id, data) VALUES ('$id', '$data')
ON DUPLICATE KEY UPDATE data='$data'", $my_dbh);
mysql_query("COMMIT TRANSACTION", $my_dbh);
}
function my_destroy($id)
{
global $my_dbh;
return mysql_query("DELETE FROM session WHERE id = '$id'", $my_dbh);
}
// delete idle sessions
function my_gc($lifetime)
{
global $my_dbh;
mysql_query("DELETE FROM session WHERE
usetime < DATE_SUB(NOW(), INTERVAL $lifetime SECOND)", $my_dbh);
}
Performance and Scalability
In order to meet the requirements of satisfying performance and
scalability we have to consider the following aspects:
Solutions are discussed in this section: using distributed systems,
load balancing and load sharing as well as data partioning.
Distributed System
In a distributed environment all system load (user web requests
generated by a page hit causing a session call) is distributed
to multiple web server instances usually located on different
computers. A distributed allows to increase the overall
throughput of the web system and can perform a fail-over in case
of a system failure.
Load Balancing
Basically two methods to load balance your application exist:
Partitioning / "Sticky Connections"
In order to distribute load to different web servers a central session storage
or local session storages are needed. In case of a central storage each single
user request can be routed to any server. The session data connected to the session
id will be read from the central storage.
But a shared storage will introduce a single point of failure.Fail-Over and Availability
Easiest minimum security against data loss is an external external
storage (single point of failure).
Problems:
MySQL Cluster & PHP for Session Management
Cluster for Session Management
Web Applications and Cluster
Cluster advantages
Session handling with Cluster
PHP and Cluster
Changing the PHP session interface we've seen earlier to use MySQL only
requires a change of the storage engine:
ALTER TABLE session ENGINE=ndbcluster;
Solution advantages
Literature