Switching from session to cookie can help you avoid some of the pitfalls of sessions. A J2EE book I read long ago also pointed out that sessions should not be used in a cluster system, or you’ll be asking for trouble. If your system is not overly complex, prioritize evaluating whether you can drop sessions altogether. If the modifications are too cumbersome, then consider the methods below.
2) Application Server Self-Implemented Sharing
As we know, PHP can use databases or memcached to store sessions, thereby creating a session cluster within PHP itself. This approach ensures session stability鈥攅ven if a node fails, the session won’t be lost. It’s suitable for scenarios with strict requirements but moderate request volumes. However, its efficiency is not very high, making it unsuitable for high-performance demanding situations.
The two methods above have little to do with nginx. Now let’s discuss how to handle this with nginx:
3) ip_hash
The ip_hash technique in nginx can direct requests from a specific IP to the same backend server. This way, a client at that IP can establish a stable session with a particular backend. ip_hash is defined within the upstream configuration:
upstream backend {
server 127.0.0.1:8001;
server 127.0.0.1:8002;
ip_hash;
}
ip_hash is easy to understand, but because it distributes backend requests based solely on the IP factor, it has limitations and cannot be used in certain situations:
1/ nginx is not the frontmost server. ip_hash requires nginx to be the very frontmost server; otherwise, nginx won’t get the correct IP and cannot hash based on it. For example, if Squid is used as the frontmost server, nginx will only get Squid’s server IP address when fetching the IP. Using that address for traffic distribution will certainly cause chaos.
2/ There are other load balancing methods behind nginx’s backends. If there is another layer of load balancing behind nginx that distributes requests through other means, then a certain client’s requests definitely cannot be pinned to the same session application server. With this in mind, nginx backends should only point directly to application servers, or point to a Squid instance that then points to the application server. The best approach is to use locations for primary traffic splitting: direct the part of requests that need sessions through ip_hash, and route the rest to other backends.
4) upstream_hash
To solve some of ip_hash’s problems, you can use the third-party upstream_hash module. This module is often used as url_hash in most cases, but that doesn’t prevent it from being used for session sharing:
If the frontend is Squid, it will add the IP into the x_forwarded_for HTTP header. Using upstream_hash, you can use this header as a factor to direct requests to a specified backend:
See this document:
http://www.oschina.net/discuss/thread/622
In that document, $request_uri is used as the factor. Modify it slightly:
hash $http_x_forwarded_for;
This changes the factor to the x_forwarded_for header. In newer versions of nginx, reading cookie values is supported, so you can also change it to:
hash $cookie_jsessionid;
If PHP’s session is configured as cookieless, you can use nginx’s own userid_module to make nginx issue a cookie spontaneously. Refer to the userid module’s English documentation: