Redis como Session Handler en PHP

13:46 0 Comments A+ a-


En este articulo se configurara dos Apache Server para que guarden las sesiones de los cliente en un Servidor Redis. De esta forma ambos servidores pueden acceder a las sesiones de los cliente.

La configuración es la siguiente:

Tengo 2 nodos:
  • Nodo A IP: 192.168.0.3
  • Nodo B IP: 192.168.0.12
En el Nodo A, esta corriendo los siguientes servicios:
  • Nginx Server
  • Redis Server
  • Apache Server

Nodo B:
  • Apache Server

Nodo A corre sobre Fedora 21, Nodo B corre sobre Fedora 20.



  • Los clientes realizan petición contra el servidor de Nginx
  • El Servidor Nginx enruta las peticiones hacia el Servidor Apache en el Nodo A. En caso de que el Servidor Apache del Nodo A no este disponible, entonces Nginx enrutara las peticiones hacia el Servidor Apache del Nodo B
  • Las sesiones que se crearan en el Servidor de Redis, y cada vez que se necesite leer la data de una sesion se realizara contra el Servidor de Redis


Como funcionan las sesiones.


Es necesario instalar y configurar en ambos Apache Server la extensión PHP-Redis que permite la comunicación con un servidor Redis: http://pecl.php.net/package/redis

Ambos Apache Server están corriendo sobre el puerto 8080. Nginx estará corriendo sobre el puerto 80 en el Nodo A. Utilizare el servidor de Nginx como Load Balancer para los Apache Server configurados en los dos nodos. El Apache Server del Nodo A, sera configurado como primario, y recibirá todas las conexiones entrantes. El Apache Server del Nodo B, sera configurado como Failover, osea que cuando el Apache Server del Nodo A no responda, entonce Nginx enrutará todas las conexiones hacia el Apache Server del Nodo B.

Configuración de NGINX
Código: INI
  1. upstream httpbackendserver {
  2.     server 192.168.0.3:8080;
  3.     server 192.168.0.12:8080 backup;
  4.  
  5.     }
  6.  
  7.     server {
  8.         listen       80 default_server;
  9.         server_name  localhost;
  10.  
  11.         # Load configuration files for the default server block.
  12.         include /etc/nginx/default.d/*.conf;
  13.  
  14.         location / {
  15.             proxy_pass http://httpbackendserver;
  16.         }
  17.  
    Directivas importantes:
    • upstream: sirve para definir un grupo de server. La usaremos para definir nuestro HTTP Server.
    • server: sirve para definir un servidor y sus parámetros. En este caso definimos el servidor del nodo B, con el parámetro backup.

    Luego de instalar la extensión de Redis para PHP, de haber reiniciado el servidor Apache, entonces hay que configurar PHP para que almacenes las sesiones en el servidor de Redis. De esta forma cada vez que se vaya a utilizar sesiones, hay que utilizar Redis como repositorios de las sesiones. Para indicar que Redis maneje la sesiones guardada, hay que configurar las directivas
session.save_handler y session.save_path del php.ini, de esta forma:
Código: INI
  1. session.save_handler = redis
  2. session.save_path    = tcp://redis-host:redis-port

En mi caso lo hice un poco mas portable, modifico las directivas desde un archivo PHP (teniendo en cuenta que la modificación solo tendrá efecto siempre y cuando se ejecute el mismo archivo PHP).

Código: PHP (brief)
  1. <?php
  2.  
  3. ini_set('session.save_handler', 'redis');
  4. ini_set('session.save_path',    'tcp://192.168.0.3:6379');
  5.  
  6.  
  7.  
  8. echo "Server 1,  ";
  9. if(!empty($_GET['set'])) {
  10.     $_SESSION['data'] = $_GET['set'];
  11. }
  12.  
  13. if(!empty($_GET['show']) && $_GET['show'] == 1) {
  14.  echo "Session data: ".$_SESSION['data'];
  15. }
  16.  
  17.  
  18. echo "Hola mundo";
  19. ?>

Tengo las siguientes URL:
  • 192.168.0.3/test.php?set=data_a_setear
  • 192.168.0.3/test.php?show=1
La primera URL se utiliza para setear información a la sesión data. La segunda URL se utiliza para ver la información que contiene la sesión data.




Bajo el servidor Apache del Nodo 1, para que Nginx enrute todas las peticiones hacia el servidor de Apache del nodo 2.



De esta forma se puede ver que Nginx ha enrutado todas las peticiones hacia el Servidor Apache en el Nodo B, y el Servidor Apache en el Nodo B utiliza la data de la sesiones creada en el Servidor Apache en el Nodo A.

Data de la sesion guardada en el Servidor de Redis:
Código: Bash
  1. [yoya@127 ~]$ redis-cli
  2. 127.0.0.1:6379> KEYS *
  3. 1) "PHPREDIS_SESSION:n30kep1lkgnks7knlkppps6c10"
  4. 127.0.0.1:6379> get "PHPREDIS_SESSION:n30kep1lkgnks7knlkppps6c10"
  5. "data|s:9:\"Underc0de\";"
  6. 127.0.0.1:6379>
  7.  


Este tipo de configuración se puede utilizar en ocasiones en la que es posible que no siempre el mismo servidor maneje la comunicación  con el mismo cliente. También en ocasiones en que se esta trabajando una mejora de la misma aplicación y se desea que los cliente no tengan ningún tiempo de inactividad en la transferencia de la aplicación vieja a la aplicación nueva.

También hay que tener en cuenta el acceso a la sesiones en Redis sera mas rápido que acceder a la información de la sesiones almacenadas en archivos en el sistema operativo, ya que la información en Redis reside en la memoria. Pero esta afirmación dependerá del contexto donde se encuentre los servidores.

Existe configuraciones similares para el manejo de sesiones como realizar un shared disk para almacenar los archivos de sesiones generados en los servidores.

Saludos!

URLs:
http://php.net/manual/en/session.configuration.php#ini.session.save-handler
http://php.net/manual/en/session.configuration.php#ini.session.save-path
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server
http://www.if-not-true-then-false.com/2011/install-nginx-php-fpm-on-fedora-centos-red-hat-rhel/
http://pecl.php.net/package/redis
http://phpave.com/installing-php-redis-a-php-extension-for-redis/