Mostrando entradas con la etiqueta scalability. Mostrar todas las entradas
Mostrando entradas con la etiqueta scalability. Mostrar todas las entradas

Varnish, configuración avanzada

El otro día comentamos cómo instalar Varnish en nuestro equipo y configurarlo para que cachee contenidos a nivel local, pero también hablamos de que podía hacer de proxy inverso para nuestros sistemas. Es decir, podemos tener un número n de servidores con Apache (por ejemplo) sirviendo una página web y que todo el contenido estático lo sirva Varnish, dejando la parte dinámica en round-robin entre los servidores de backend. Toda la configuración es la misma que la presentada en el post de instalación. Lo único que cambiará será el contenido del fichero /etc/varnish/default.vcl, que contendrá los equipos a los que conectarse.
director www_master round-robin {
   { .backend = { .host = "192.168.0.33"; .port = "http"; } }
   { .backend = { .host = "192.168.0.34"; .port = "http"; } }
}
 
sub vcl_recv {
   set req.backend = www_master;
   remove req.http.X-Forwarded-For;
   set req.http.X-Forwarded-For = client.ip;
}
E incluso una configuración más compleja, con varios virtualhost y varios servidores de backend
director web_master round-robin {
   { .backend = { .host = "192.168.0.33"; .port = "http"; } }
   { .backend = { .host = "192.168.0.34"; .port = "http"; } }
}
 
director mail_master round-robin {
   { .backend = { .host = "192.168.0.37"; .port = "8080"; } }
   { .backend = { .host = "192.168.0.65"; .port = "80"; } }
}
 
director photos_master round-robin {
   { .backend = { .host = "192.168.0.100"; .port = "http"; } }
}
 
sub vcl_recv {
   if (req.http.host ~ "^(mail.|webmail.)?domain.(com)$") {
      set req.backend = mail_master;
   }
 
   if (req.http.host ~ "^(fotos.|photos.)doamin.(com)$") {
      set req.backend = photos_master;
   }
 
   if (req.http.host ~ "^(www.)?doamin.(com)$") {
      set req.backend = web_master;
   }

   remove req.http.X-Forwarded-For;
   set req.http.X-Forwarded-For = client.ip;
}
Leer más

Varnish, cacheando contenido

Varnish es un pequeño servidor que actúa como proxy-caché de nuestro servidor web y que permite reducir notablemente las consultas a disco y por lo tanto acelerar las respuestas de la web. Varnish es por lo tanto un proxy inverso para un servidor web (Apache, Cherokee, etc) que permite a la vez que servir contenidos también mantenerlos en caché, acelerando así las respuestas. Aunque las páginas sean dinámicas y necesiten ser consultas a una base de datos, Varnish lo hace por nosotros, almacenando la página como estática en la memoria para que devolverla al cliente sea inmediato.
Varnish es software libre y está disponible en los repositorios de las principales distribuciones. Como lenguaje de configuración usa VLC (Varnish Configuration Language), un lenguaje propio que permite darle la flexibilidad y personalización que cada entorno necesita.
En este post vamos a configurar Varnish de forma sencilla para que nos cachee los contenidos de un servidor web (Apache) local que tenemos.
  1. Instalación
    Al emplear Debian como sistema operativo tenemos el paquete compilado en los repositorios oficiales.
    shell> apt-get install varnish
    
  2. Configuración de apache
    Como servidor de backend vamos a tener nuestro servidor Apache montado y escuchando en la IP pública o IP de DMZ correspondiente. Puesto que dejaremos que sea Varnish el encargado de servidor la web, es decir, escuchar en el puerto 80 de la IP "pública", configuraremos Apache para que escuche en el interfaz de localhost. Para ello editamos el fichero /etc/apache2/ports.conf dejándolo como sigue.
    NameVirtualHost 127.0.0.1:8080
    Listen 127.0.0.1:80
    
    <IfModule mod_ssl.c>
        Listen 443
    </IfModule>
    
    <IfModule mod_gnutls.c>
        Listen 443
    </IfModule>
    
    Fijaros que en esta configuración sólo cambiamos el puerto 80 de escucha a localhost. Si hay algo sirviéndose en https (puerto 443) será entregado por Apache directamente.
  3. Configuración de varnish
    Ahora que ya tenemos el backend en localhost:80 tenemos que configurar Varnish para que escuche en el puerto 80 de la IP "pública" y que envíe dichas peticiones al backend.
    Lo primero de todo, configurar el comportamiento por defecto del nuevo servicio. En este caso editamos el fichero /etc/default/varnish.
    START=yes
    
    DAEMON_OPTS="-a 192.168.0.33:80 \
        -T 192.168.0.33:6082 \
        -u varnish \
        -g varnish \       
        -f /etc/varnish/default.vcl \
        -S /etc/varnish/secret \
        -s file,/var/lib/varnish/varnish_storage.bin,1G"
    
    Una vez que ya tenemos esto, simplemente queda por crear el contenido del fichero /etc/varnish/default.vcl, que tendrá el comportamiento del servicio propiamente dicho.
    director www_master round-robin {
       { .backend = { .host = "127.0.0.1"; .port = "80"; } }
    }
     
    sub vcl_recv {
       set req.backend = www_master;
       remove req.http.X-Forwarded-For;
       set req.http.X-Forwarded-For = client.ip;
    }
    
    Este fichero es muy simple, puesto que no hay nada especial en él, simplemente indicamos que el proveedor de datos (Apache) está en localhost:80.
  4. Arrancando servicios
    Ahora que ya está todo guardado, simplemente lanzamos los servicios para que nuestro servidor quede nuevamente funcionando, pero con un proxy caché intermedio.
    shell> /etc/init.d/apache2 restart
    shell> /etc/init.d/varnish start
    
Leer más

Y tú, ¿aún no automatizas tareas con puppet?

El otro día @pepellou retwitteó el siguiente contenido,

Y la verdad es que el contenido está en sí muy bien. Representa en una línea muy clara lo que implica en administración de sistemas la automatización. Fuera del término 'geek', automatizar puede suponer una gran ventaja a la hora de ahorrarse trabajo y sobre todo, evitar fallos por replicación.
En el gráfico del tweet se representaba la diferencia entre administradores 'geeks' y 'no geeks'. Yo quiero subir un nivel y demostrar la verdadera potencia de puppet.
puppet: simple automatization
Juzgarlo vosotros: ¿vale la pena? ;-)


Si este artículo te ha interesado, quizás te puedan interesar también:
Leer más

zabbix-proxy: Instalación

La instalación de proxy's por la red es uno de los puntos fuertes de zabbix, que permite así escalar la recolección de datos desde un único punto a varios puntos, aunque siga a centralizar todos los datos sobre una misma base de datos y de consulta. La idea es que desde un punto centralizado (zabbix_server) estén todos los datos pero que la recolección de los mismos se haga desde varios puntos deferentes, para así poder levantar el número de threads necesarios de cada poller y distribuir la carga de CPU entre varias máquinas. 'divide y vencerás'.
Antes de comenzar con la instalación de un zabbix-proxy hay que aclarar un par de conceptos.
  1. La cantidad de equipos que cada uno de los proxy's va a controlar y la frecuencia de los check's. Es decir, cuantos vps va a tener que soportar la base de datos. No hay un número exacto que podamos decir, pero esto es importante pues según estos datos tendremos que optar por instalar un proxy con sqlite o un proxy con una base de datos más potente (mysql o postgress).
  2. El tipo de proxy que vamos a tener:
    • Activo
      El propio proxy enviará la información al servidor zabbix según la configuración que tenga. El servidor únicamente tendrá que atender las peticiones y recolectar los datos.
    • Pasivo
      Será el propio servidor zabbix el que se encargue de pedirle al proxy los datos con una frecuencia determinada.
Una vez tengamos esto decidido ya es hora de instalar el servicio y de configurarlo sobre todo.
  • SQLite
    Esta es la solución más sencilla y no necesita prácticamente nada. Simplemente se instala y la configuración de la base de datos es inmediata. El propio proceso la crea al arrancar por primera vez, no hay que desplegar el schema.
    shell> apt-get install zabbix-proxy-sqlite
    
  • MySQL
    Esta es junto con la opción de postgress la opción a elegir si tenemos más carga de trabajo en el proxy. Vamos a partir de que la instalación del servidor MySQL ya está realizada. Por lo tanto sólo queda instalar el servicio y desplegar el schema de zabbix.
    • Instalamos el servicio
      Primero vamos a instalar el servicio de zabbix-proxy. Para eso empleamos el gestor de paquetes de nuestra distribución.
      shell> apt-get install zabbix-proxy-mysql
      
    • Configuramos la base de datos
      La versión de MySQL no instala la base de datos al arrancarse por primera vez, así que tenemos que desplegar el schema y crear un usuario con acceso a la nueva base de datos del proxy. El schema que emplea es el mismo que el servidor zabbix, pero el proxy no necesita datos, esos se los provee el servidor en su debido momento.
      mysql> CREATE DATABASE zabbix_proxy_1;
      mysql> USE zabbix_proxy_1;
      mysql> SOURCE ~/create/schema/mysql.sql
      mysql> GRANT ALL PRIVILEGES ON zabbix_proxy_1.*
             -> to 'proxy_1'@'192.168.1.51'
             -> IDENTIFIED BY 'YOURPASSWD';
      
    • Configuramos zabbix_proxy.conf para emplear MySQL
      Esta parte es específica si empleamos una base de datos diferente a SQLite.
      ...
      DBHost     = 192.168.1.33
      DBName     = zabbix_proxy_1
      DBUser     = proxy_1
      DBPassword = YOURPASSWD
      ...
      
Una vez esté todo instalado hay que realizar la configuración del servicio como primer paso antes de arrancarlo. Esta configuración se lleva a cabo en el fichero /etc/zabbix/zabbix_proxy.conf y está perfectamente documentada en la documentación oficial. Al finalizar la configuración, arrancamos el servicio y desde el servidor zabbix creamos un nuevo proxy (Administration/DM/Proxy), según sea activo o pasivo.
Create a zabbix new proxy
Una vez tengamos el nuevo proxy creado, todos aquellos equipos que nos interese monitorizar a través de él tendremos que indicarlo desde el interfaz web y en su fichero de configuración indicar que la IP del servidor zabbix será la del proxy y no la del servidor real.
Leer más

Comandos interesantes, dsh

Hoy navegando por la inmensa lista de paquetes que proporciona Debian me encontré con una herramienta cuando menos interesante, dsh. Es un comando que permite conectar de forma remota con un grupo de máquinas de forma que facilita enormemente la ejecución del mismo comando en diferentes máquinas. O dicho de otra forma... es un pequeño script que va iterando entre un grupo de máquinas y conectándose y ejecutando el mismo comando en todas y cada una de ellas.
Vamos primeramente a instalarlo. Los sistemas basados en Debian lo incluyen en su repositorio, por lo tanto,
shell> apt-get install dsh
Una vez esté instalado, lo primero que tenemos que hacer es editar el fichero de configuración (/etc/dsh/dsh.conf) y cambiar la shell remota que emplea por defecto de rsh a ssh. Hay que securizar nuestros entornos ;-)
# default configuration file for dsh.

verbose = 0 
remoteshell = ssh
showmachinenames = 0
waitshell = 1  # whether to wait for execution

#remoteshellopt=...
Una vez tengamos esto listo, sólo faltará crear el grupo de máquinas a las que nos interesa conectar. Un grupo no es más que un fichero que contiene un listado de nombres o IP's a las que conectarse. Una por línea. Por lo tanto, crearemos el siguiente fichero, maquinas_locales, que tendrá las máquinas GNU/Linux de nuestra red local. Dicho fichero lo colocaremos en /etc/dsh/group/maquinas_locales y el contenido será,
shell> cat /etc/dsh/group/maquinas_locales 
puppet.local.net
apache.local.net
dhcp.local.net
192.168.1.33
192.168.1.45
192.168.1.24
localhost
Como se observa aquí, incluimos tanto nombres como IP's y puesto que también nos interesa que nuestra máquina local esté afectada por los comandos, también la incluimos.
Podemos crear tantos grupos como queramos con las máquinas que nos interese, únicamente habrá que acordarse del nombre.
Vamos ahora a comenzar a trabajar contra todos los equipos. Por ejemplo, vamos a solicitar la salida del comando uptime. Entonces... según las diferentes opciones que presenta dsh,
  • Ejecución al grupo all (por defecto)
    shell> dsh -a uptime
    
  • Ejecución del comando a una máquina concreta
    shell> dsh -m 192.168.1.33 -m puppet.local.net uptime
    
  • Ejecución del comando a un grupo de máquinas
    Por defecto, según lo especificado en el fichero de configuración, se lanza el comando y se espera a que se ejecute antes de "lanzarlo" a otra máquina.
    shell> dsh -g maquinas_locales uptime
    
  • Ejecución del comando a un grupo de máquinas de forma concurrente
    shell> dsh -c -g maquinas_locales uptime
    
  • Ejecución del comando indicando en qué máquina se ejecuta
    Por defecto no indica el nombre de la máquina, esto implica que no sepamos de qué máquina proviene.
    shell> dsh -M -g maquinas locales uptime
    
La idea de emplear ssh como shell por defecto, es por motivos de seguridad y también por que tenemos la clave ssh compartida entre las máquinas locales, por lo que no tendremos que repetir una y otra vez la contraseña cada vez que nos tengamos que conectar a una nueva máquina. Algo importante y que sirve para automatizar aún más el proceso.
Leer más

Llenado del 'buffer pool' en InnoDB, MySQL

En un post anterior se habló ya de las ventajas de tener pre-cacheados los datos de determinadas consultas en servidores MySQL que no se estén usando (SLAVE's), para que en el momento que entren en funcionamiento, tengan un buen rendimiento.
La posibilidad de hacer esto, estaba disponible en percona desde hace varias versiones y en la última versión de MySQL, la 5.6 también la incorporaron para facilitar el escalado de servidores MySQL.
El funcionamiento de éste, sin embargo es diferente y para usarlo, se podría hacer tal como sigue.
  • Crear un dump del buffer_pool
    mysql> SET innodb_buffer_pool_dump_now=ON;
    
  • Crear un dump del buffer_pool cuando se cierre el servidor
    mysql> SET innodb_buffer_pool_dump_at_shutdown=ON;
    
  • Subir a memoria un dump
    mysql> SET innodb_buffer_pool_load_now=ON;
    
  • Ver el progreso de construcción de un dump
    mysql> SHOW STATUS LIKE 'innodb_buffer_pool_dump_status';
    
  • O de restauración
    mysql> SHOW STATUS LIKE 'innodb_buffer_pool_load_status';
    
  • O cancelarlo
    mysql> SET innodb_buffer_pool_load_abort=ON;
    
Si queremos habilitarlo, al igual que en percona, se puede añadir la siguiente línea al fichero de configuración (/etc/my.cfg).
innodb_buffer_pool_load_at_startup=ON
Leer más

Llenado del 'buffer pool' en InnoDB, Percona

Si estás trabajando con una arquitectura MASTER-SLAVE y necesitas un óptimo rendimiento, puede darse el caso de que cuando el servidor SLAVE entra en funcionamiento, todas las consultas que estaban ya en caché en el MASTER en éste no están y eso conlleva un gran problema, ya que las primeras consultas serán muy lentas y habrá que ir a buscar todos los datos a disco. Si trabajamos en un sistema de alto rendimiento y disponibilidad, esto puede tener consecuencias importantes, como parón en el servicio o carga muy alta en el servidor de base de datos.
para solucionar ésto, tradicionalmente se empleaba un método más rudimentario, que era lanzar cada X tiempo un script que realizase dichas consultas y por lo tanto, MySQL las pre-cachease. Esto no tenía mucho sentido, por lo que la gente de Percona optó por crear una forma más óptima de realizar este llenado del buffer de las tablas InnoDB y evitar así que en el arranque del SLAVE las consultas sean tan pesadas.
Para usar esta facility,
  • Crear un dump del buffer_pool
    mysql> use information_schema;
    mysql> select * from XTRADB_ADMIN_COMMAND /*!XTRA_LRU_DUMP*/;
    
  • Subir un dump a memoria
    mysql> use information_schema;
    mysql> select * from XTRADB_ADMIN_COMMAND /*!XTRA_LRU_RESTORE*/;
    
    
  • Programar un dump cada X segundos
    mysql> set innodb_auto_lru_dump = 60;
    
  • Cargar automáticamente un dump tras reinicio
    shell> vi /etc/my.cnf
      innodb_buffer_pool_restore_at_startup=1
    
Leer más

MySQL: query profiler

Una de las grandes innovaciones de MySQL en la versión 5 fue incluir un pequeño truco, no muy extendido, que permite detectar problemas de rendimiento en nuestra BD: query profiler.
Esta funcionalidad, desactivada por defecto en MySQL, desglosa cada una de las partes de las que se compone una consulta. Está especialmente pensado para query's complejas, con varios join's. De esta forma se podrían optimizar mejor las consultas a la BD y así obtener un mejor rendimiento. Gracias a ella podemos descubrir en qué partes la consulta es más rápida y cual es la que le lleva más tiempo realizar. Un ejemplo:
mysql> set profiling=1;
Query OK, 0 rows affected (0.00 sec)

mysql> show databases;
+------------------------+
| Database               |
+------------------------+
| CV                     |
| documentacion          |
| gastos                 |
| mysql                  |
| test                   |
| viajes                 |
+------------------------+
23 rows in set (0.00 sec)

mysql> use gastos;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed

mysql> show profiles;
+----------+------------+---------------------------+
| Query_ID | Duration   | Query                     |
+----------+------------+---------------------------+
|        1 | 0.00037500 | show databases            |
|        2 | 0.00012600 | SELECT DATABASE()         |
|        3 | 0.19438700 | select count(*) from fact |
+----------+------------+---------------------------+
6 rows in set (0.00 sec)

mysql> select count(*) from facturacion;
+----------+
| count(*) |
+----------+
|   239319 |
+----------+
1 row in set (0.19 sec)

mysql> show profile for query 3;
+--------------------------------+----------+
| Status                         | Duration |
+--------------------------------+----------+
| starting                       | 0.000011 |
| checking query cache for query | 0.000026 |
| Opening tables                 | 0.000009 |
| System lock                    | 0.000003 |
| Table lock                     | 0.000026 |
| init                           | 0.000008 |
| optimizing                     | 0.000003 |
| statistics                     | 0.000007 |
| preparing                      | 0.000004 |
| executing                      | 0.000004 |
| Sending data                   | 0.193768 |
| end                            | 0.000012 |
| query end                      | 0.000003 |
| freeing items                  | 0.000159 |
| storing result in query cache  | 0.000290 |
| logging slow query             | 0.000002 |
| logging slow query             | 0.000048 |
| cleaning up                    | 0.000004 |
+--------------------------------+----------+
18 rows in set (0.00 sec)

mysql> set profiling=0;
Query OK, 0 rows affected (0.00 sec)

La sintaxis del comando es:
SHOW PROFILE [type [, type] ... ]
    [FOR QUERY n]
    [LIMIT row_count [OFFSET offset]]
Donde type puede ser alguno de estos valores:
  • ALL: Muestra toda la información.
  • BLOCK IO: Muestra los bloqueos de I/O.
  • CONTEXT SWITCHES: Muestra las alternancias entre contextos voluntarios e involuntarios.
  • CPU: Tiempo de CPU.
  • IPC: Mensajes enviados y recibidos.
  • PAGE FAULTS: Contador de major y minor pages.
  • SOURCE: Muestra el nombre de las funciones del código y la línea.
  • SWAPS: Contador de swap.
Por ejemplo, la query anterior mostrando los consumos de CPU quedaría,
mysql> show profile cpu for query 6;
+---------------------------+----------+----------+------------+
| Status                    | Duration | CPU_user | CPU_system |
+---------------------------+----------+----------+------------+
| starting                  | 0.000011 | 0.000000 |   0.000000 |
| checking query cache for  | 0.000026 | 0.000000 |   0.000000 |
| Opening tables            | 0.000009 | 0.000000 |   0.000000 |
| System lock               | 0.000003 | 0.000000 |   0.000000 |
| Table lock                | 0.000026 | 0.000000 |   0.000000 |
| init                      | 0.000008 | 0.000000 |   0.000000 |
| optimizing                | 0.000003 | 0.000000 |   0.000000 |
| statistics                | 0.000007 | 0.000000 |   0.000000 |
| preparing                 | 0.000004 | 0.000000 |   0.000000 |
| executing                 | 0.000004 | 0.000000 |   0.000000 |
| Sending data              | 0.193768 | 0.140009 |   0.012001 |
| end                       | 0.000012 | 0.000000 |   0.000000 |
| query end                 | 0.000003 | 0.000000 |   0.000000 |
| freeing items             | 0.000159 | 0.000000 |   0.000000 |
| storing result in query   | 0.000290 | 0.000000 |   0.000000 |
| logging slow query        | 0.000002 | 0.000000 |   0.000000 |
| logging slow query        | 0.000048 | 0.000000 |   0.000000 |
| cleaning up               | 0.000004 | 0.000000 |   0.000000 |
+---------------------------+----------+----------+------------+
18 rows in set (0.00 sec)
La utilidad es grande, ya que si observamos que una parte concreta de la query tarda mucho en ejecutarse, podemos optimizar dicha parte, ya sea la propia query o pensar en realizar, por ejemplo un índice que la acelere.
Leer más

Round Robin DNS


Una de las formas más simples de escalar una aplicación web (o cualquier otro servicio) es la conocida como Round Robin DNS. RR-DNS es una técnica de balanceo de carga realizada desde los propios servidores DNS y no desde una máquina dedicada.
Round Robin es un algoritmo que permite seleccionar elementos de forma equitativa y por orden. Generalmente lo que se hace es crear una lista con todos los elementos y éstos luego son devueltos en orden. Cuando se ha recorrido toda la lista, se comienza de nuevo. Si se aplica este algoritmo a DNS, se puede comprender la forma de funcionamiento. Un nombre DNS tiene varias IP's detrás que pueden contestar a él, albergadas en diferentes servidores. Cuando un cliente pide la página, se envía a un servidor, al siguiente cliente se le mandará al siguiente servidor y así siempre. La carga se distribuye a través de los N equipos que formen el cluster, pero todo desde un DNS.
Leer más

MySQL: cambio del prompt

Algunas veces, especialmente al conectarnos desde un único equipo a varios servidores mysql diferentes, puede pasar que al final no se sepa en qué equipo se está. Por ejemplo, en una arquitectura master-slave o en una arquitectura mysql-cluster esto es muy fácil que suceda.
Para evitarlo, al lanzar la conexión contra dicho equipo, se puede modificar el prompt de mysql y así saber siempre en qué equipo se está ejecutando cada comando.
El comando mysql tiene una variable que nos permite sobreescribir dicho dato, que es "--prompt". La forma de usarla, a continuación.
shell> mysql -h 192.168.1.30 -u root -p --prompt 'server1> '
server1> 
Leer más

Formulario de contacto

Nombre

Correo electrónico *

Mensaje *

Últimos comentarios