Balanceo de carga con nginx a dos WebAPP de Azure

En el post anterior vimos como instalar un servidor nginx. Una de las capacidades que tiene ngin-x es ser un potente servidor proxy, utilizado como balanceador de carga. En este post vamos a ver como usarlo para balancear la carga de dos WebAPPs (podrían ser tantas como fueran necesarias). Este escenario presenta una particularidad que obliga a modificar ligeramente el procedimiento normal para esta operación.

Partimos de una máquina linux con ngin-x instalado, tal como se vió en el post anterior.

Además vamos a crear dos WebAPPs simples, con un mensaje que nos diferencie entre cada una de ellas por ejemplo, tal como se ve en las siguientes imágenes:

20160505_NGINX_WebAPP_Paso02

20160505_NGINX_WebAPP_Paso03

A continuación vamos a configurar ngin-x siguiendo las pautas normales. Entramos al servidor linux en una consola de comando y editamos el fichero de congiguración con nano por ejemplo:

sudo nano /etc/nginx/nginx.conf

Y modificamos el script para que quede como el siguiente código:

user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
     worker_connections 768;
     # multi_accept on;
}

http {
     upstream bloqueprimerproxy {
          server xxURL1xx.azurewebsites.net;
          server xxURL2xx.azurewebsites.net;
     }

     server {
          listen 80;
          server_name   localhost;

          location / {
               proxy_pass http://bloqueprimerproxy;
               proxy_set_header  X-Real-IP  $remote_addr;
          }
     }
}

En donde xxURL1xx.azurewebsites.net y xxURL2xx.azurewebsites.net son las URLs de las dos WebAPPs a balancear.

Grabamos el código y reiniciamos el servicio ngin-x con:

sudo service nginx restart

El script anterior sería la forma normal de balancear dos WEBs con ngin-x. Pero si lo probamos ahora obtendremos el siguiente error:

20160505_NGINX_WebAPP_Paso01

Ésto se debe a que Azure App Service usa cookies para ARR (Application Request Routing). Es necesario asegurarse que el proxy pasa la cabecera de forma correcta a la WebAPP para que ésta identifique la petición correctamente.

Para esto editamos de nuevo el fichero de configuración y lo dejamos como sigue:

user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
     worker_connections 768;
     # multi_accept on;
}

http {
     upstream bloqueprimerproxy {
         server localhost:8001;
         server localhost:8002;
     }

     upstream servidor1 {
         server xxURL1xx.azurewebsites.net;
     }

     upstream servidor2 {
         server xxURL2xx.azurewebsites.net;
     }

     server {
          listen 80;
          server_name   localhost;

          location / {
               proxy_pass http://bloqueprimerproxy;
               proxy_set_header    X-Real-IP    $remote_addr;
          }
     }

     server {
          listen 8001;
          server_name   servidor1;

          location / {
               proxy_set_header Host xxURL1xx.azurewebsites.net;
               proxy_pass http://servidor1;
          }
     }

     server {
          listen 8002;
          server_name   servidor2;

          location / {
               proxy_set_header Host xxURL2xx.azurewebsites.net;
               proxy_pass http://servidor2;
          }
     }
}

En donde igual que antes xxURL1xx.azurewebsites.net y xxURL2xx.azurewebsites.net son las URLs de las dos WebAPPs a balancear.

En este script lo que hacemos es aplicar un doble proxy, de tal forma que balanceamos la entrada contra el mismo ngin-x, atacando por los puertos 8001 y 8002, del cual encaminamos a las WebAPPs, pero añadiendo a la cabecera la URL real de la WebAPP.

Tras grabar el script y reiniciar el servicio ngin-x, si entramos al mismo veremos que nos balancea de una a otra web sin problema.

Para saber más sobre los modos de balanceo disponibles en ngin-x podeis consultar este enlace.

 

 

Isaac Lázaro

gigaSACs es un sitio web dedicado a escribir sobre Cloud Computing y programación, siendo los temas principales Azure, .NET, SQL Server, Wintel, Linux, Java, y la tecnología en general.