Wednesday, October 13, 2010

Maintaining PHP Sessions Across Multiple Machines

As you may know if you've ever tried to play PhotoCity, the website likes to randomly log you out and make you log back in again before uploading more photos or checking on your progress. The reason is that there are multiple machines in a round robin hosting the website, the website uses sessions, and when a different machine picks up your request, it doesn't know about the session that says you were logged in that the first machine was using.

How to keep sessions alive and consistent across multiple machines?? Some people told me a load balancer was the answer, but since I don't actually maintain the machines myself, that wasn't an option for me.

Yesterday afternoon, I had a list of 4 potential things to work on. Vanquishing this obnoxious sessions problem was one of them. True story: I flipped a 4-sided coin/generated a random number in python, got a 3, and set to work investigating cookies vs. sessions and possible solutions. What I learned:

This is the main website I read:
http://www.tuxradar.com/practicalphp/10/0/0

Lesson 1: Cookies are cool and all (and look easy to use) and are stored locally, but they are too easy to tinker with. I could have stored a player's ID in a cookie and then checked which player was logged in, but the player could have changed a field in the cookie file to be someone else's player ID and then logged in as someone else.

Lesson 2: You can write some magic code and make a new table in your database and then trick the PHP session handler to save its data to a centralized database. I believe sessions also use really small cookies, so basically there is a cookie on the user's computer that tells the database what session ID to look up. The session ID is complicated and hard to guess. E.g. "gm6uf16d20k3vt6kjq790q9fp0". Yeah!

The first step is to make a new table in your own database.
CREATE TABLE sessions (ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY, SessionID CHAR(26), Data TEXT DEFAULT '', DateTouched INT);

The next step is to write your own session handler/steal this one that I just stole from someone else. Included is a php file that uses the new session handler.
link: magical_session_handler.php (.txt file)
link: hello.php (.txt file)
(I basically borrowed the code from this page, but that one had a bug or two)
http://www.tuxradar.com/practicalphp/10/3/7

You can play with the actual webpage here and watch sessions be preserved: http://superfiretruck.com/stuff/hello.php
Without the special session handler, that page is just really simple example of sessions.

Lesson 3: THERE IS A BUG!
http://us2.php.net/manual/en/function.session-destroy.php#51001
http://bugs.php.net/32330
The super-easy answer:
By calling session_set_save_handler() again after session_destroy() it will work.

Lesson 4: If you want to display the name of the machine currently serving up your webpage (which one in your round robin, for debugging/curiosity purposes) you can write in PHP:

echo exec("hostname");

The PHP variable $_SERVER did not have quite enough information for me. However, 'hostname' is a standard unix command so you're just getting PHP to run it for you.

I haven't transferred this play example to PhotoCity yet, but I will very soon.

No comments:

Post a Comment