CHAPTER 14 – PHP Design Tip #1: Beware of State
This is the first design rule because avoiding a server-side state between requests as far as possible is helpful to scaling your application. State is infor- mation carried over from one request to the next, ranging from simple things such as a user id and password, to more complex requests such as the user's progress in a multi-page form. Of course, an application without any kind of state would be useless; this design rule is about moving state to the right place rather than eliminating it. This allows you to scale your application efficiently by simply adding servers as traffic grows.
Session State The most common form of a server-side state is ses- sions, where the browser obtains a cookie that refers to information stored on the server. By default, PHP stores session information in local files, so when you deploy that second server, each session may end up having different infor- mation stored on each server, as shown in Figure 14.1. Browser PHPSESSID=1234abc... Round-robin load-balancer Request1 Request2 Web Server 1 Web Server 2 1234abc...: 1234abc...: a=1 a=1 Session Data Session Data b=2 b=2 Fig. 14.1 Locally stored session data (state) causes problems after you go beyond one server. This application is running on two servers that are load balanced by a simple round-robin rule in the router. Both use the default (file) storage back- end for PHP sessions. The user's browser first sends a request (Request1) that is redirected to Web Server 1, along with the session id "1234abc..." When Web Server 1 responds, the session variables a and b have the values 1 and 2, respectively. Then, the browser sends another request (Request2) that the load balancer sends to Web Server 2. However, this server has different values stored for the session variables a and b, so the user receives a different result. In fact, the result may vary every time the user reloads the page.
Isolating State So, how do you fix this problem? One possibility is to store data in the user's browser via cookies. Doing so would avoid the entire state issue on the server side, but you should not store any confidential infor- mation in cookies. Cookies are easily faked and stored in plain-text files on the user's computer. The other option is to isolate the data comprising the state on the server side. You can store the session data in a database on a dedicated server, or use a dedicated session back-end server such as msession. Figure 14.2 shows how this architecture would look using a custom session handler that stores ses- sion data in a MySQL database on a different machine. Browser PHPSESSID=1234abc... Request1 Request3 Request2 Web Server 1 Web Server 2 Web Server 3 MySQL Server 1234abc...: a=1 Session Table b=2 Fig. 14.2 Session data is moved off web server machines, which allows you to scale by adding hardware. This makes the database server the single point of failure, but you can at least handle replication and failover for the database separate from scaling web servers.