HAProxy y ProxySQL son balanceadores de carga muy populares en el mundo de MySQL, pero hay una diferencia significativa entre ambos proxies. No entraremos en detalles aquí, puede leer más sobre HAProxy en el Tutorial de HAProxy y ProxySQL en el Tutorial de ProxySQL. La diferencia más importante es que ProxySQL es un proxy compatible con SQL, analiza el tráfico y comprende el protocolo MySQL y, como tal, puede usarse para dar forma al tráfico avanzado:puede bloquear consultas, reescribirlas, dirigirlas a hosts particulares, caché ellos y muchos más. HAProxy, por otro lado, es un proxy de capa 4 muy simple pero eficiente y todo lo que hace es enviar paquetes al backend. ProxySQL se puede usar para realizar una división de lectura y escritura:comprende el SQL y se puede configurar para detectar si una consulta es SELECT o no y enrutarla en consecuencia:SELECT a todos los nodos, otras consultas solo para dominar. Esta característica no está disponible en HAProxy, que tiene que usar dos puertos separados y dos backends separados para maestro y esclavo; la división de lectura y escritura debe realizarse en el lado de la aplicación.
¿Por qué migrar a ProxySQL?
Según las diferencias que explicamos anteriormente, diríamos que la razón principal por la que podría querer cambiar de HAProxy a ProxySQL es la falta de división de lectura y escritura en HAProxy. Si usa un clúster de bases de datos MySQL, y realmente no importa si se trata de una replicación asíncrona o de Galera Cluster, probablemente desee poder dividir las lecturas de las escrituras. Para la replicación de MySQL, obviamente, esta sería la única forma de utilizar su clúster de base de datos, ya que las escrituras siempre deben enviarse al maestro. Por lo tanto, si no puede realizar la división de lectura y escritura, solo puede enviar consultas al maestro. Para Galera, la división de lectura y escritura no es imprescindible, pero definitivamente es bueno tenerla. Claro, puede configurar todos los nodos de Galera como un back-end en HAProxy y enviar tráfico a todos ellos de forma rotativa, pero esto puede generar escrituras de múltiples nodos en conflicto entre sí, lo que genera bloqueos y una caída del rendimiento. También hemos visto problemas y errores dentro del clúster de Galera, para los cuales, hasta que se solucionaron, la solución alternativa era dirigir todas las escrituras a un solo nodo. Por lo tanto, la mejor práctica es enviar todas las escrituras a un nodo de Galera, ya que esto genera un comportamiento más estable y un mejor rendimiento.
Otra muy buena razón para migrar a ProxySQL es la necesidad de tener un mejor control sobre el tráfico. Con HAProxy no puede hacer nada, solo envía el tráfico a sus backends. Con ProxySQL puede dar forma a su tráfico mediante reglas de consulta (coincidencia de tráfico mediante expresiones regulares, usuario, esquema, host de origen y muchas más). Puede redirigir OLAP SELECT al esclavo de análisis (es cierto tanto para la replicación como para Galera). Puede descargar su maestro redirigiendo algunos de los SELECT fuera de él. Puede implementar el firewall SQL. Puede agregar un retraso a algunas de las consultas, puede cancelar las consultas si tardan más de un tiempo predefinido. Puede reescribir consultas para agregar sugerencias de optimización. Todo eso no es posible con HAProxy.
¿Cómo migrar de HAProxy a ProxySQL?
Primero, consideremos la siguiente topología...
Topología MySQL de ClusterControl Clúster de replicación MySQL en ClusterControlTenemos aquí un clúster de replicación que consta de un maestro y dos esclavos. Tenemos dos nodos HAProxy implementados, cada uno usa dos backends:en el puerto 3307 para maestro (escrituras) y 3308 para todos los nodos (lecturas). Keepalived se usa para proporcionar una IP virtual en esas dos instancias de HAProxy; si una de ellas falla, se usará otra. Nuestra aplicación se conecta directamente al VIP, a través de este a una de las instancias de HAProxy. Supongamos que nuestra aplicación (usaremos Sysbench) no puede hacer la división de lectura y escritura, por lo tanto, tenemos que conectarnos al backend de "escritor". Como resultado, la mayor parte de la carga está en nuestro maestro (10.0.0.101).
¿Cuáles serían los pasos para migrar a ProxySQL? Pensemos en ello por un momento. Primero, tenemos que implementar y configurar ProxySQL. Tendremos que agregar servidores a ProxySQL, crear usuarios de monitoreo requeridos y crear reglas de consulta adecuadas. Finalmente, tendremos que implementar Keepalived sobre ProxySQL, crear otra IP virtual y luego asegurarnos de que nuestra aplicación pase de HAProxy a ProxySQL de la manera más fluida posible.
Echemos un vistazo a cómo podemos lograr eso...
Cómo instalar ProxySQL
Uno puede instalar ProxySQL de muchas maneras. Puede usar el repositorio, ya sea desde el mismo ProxySQL (https://repo.proxysql.com) o si usa Percona XtraDB Cluster, también puede instalar ProxySQL desde el repositorio de Percona, aunque puede requerir alguna configuración adicional ya que se basa en la CLI. herramientas de administración creadas para PXC. Dado que estamos hablando de replicación, usarlos puede hacer que las cosas sean más complejas. Finalmente, también puede instalar archivos binarios de ProxySQL después de descargarlos de ProxySQL GitHub. Actualmente hay dos versiones estables, 1.4.x y 2.0.x. Existen diferencias entre ProxySQL 1.4 y ProxySQL 2.0 en términos de funciones, para este blog nos ceñiremos a la rama 1.4.x, ya que está mejor probada y el conjunto de funciones es suficiente para nosotros.
Usaremos el repositorio ProxySQL e implementaremos ProxySQL en dos nodos adicionales:10.0.0.103 y 10.0.0.104.
Primero, instalaremos ProxySQL usando el repositorio oficial. También nos aseguraremos de que el cliente MySQL esté instalado (lo usaremos para configurar ProxySQL). Tenga en cuenta que el proceso por el que pasamos no es de grado de producción. Para la producción, querrá al menos cambiar las credenciales predeterminadas para el usuario administrativo. También querrá revisar la configuración y asegurarse de que esté en línea con sus expectativas y requisitos.
apt-get install -y lsb-release
wget -O - 'https://repo.proxysql.com/ProxySQL/repo_pub_key' | apt-key add -
echo deb https://repo.proxysql.com/ProxySQL/proxysql-1.4.x/$(lsb_release -sc)/ ./ | tee /etc/apt/sources.list.d/proxysql.list
apt-get -y update
apt-get -y install proxysql
service proxysql start
Ahora, como se ha iniciado ProxySQL, usaremos la CLI para configurar ProxySQL.
mysql -uadmin -padmin -P6032 -h127.0.0.1
Primero, definiremos los servidores back-end y los grupos de host de replicación:
mysql> INSERT INTO mysql_servers (hostgroup_id, hostname) VALUES (10, '10.0.0.101'), (20, '10.0.0.102'), (20, '10.0.0.103');
Query OK, 3 rows affected (0.91 sec)
mysql> INSERT INTO mysql_replication_hostgroups (writer_hostgroup, reader_hostgroup) VALUES (10, 20);
Query OK, 1 row affected (0.00 sec)
Tenemos tres servidores, también definimos que ProxySQL debería usar el grupo de host 10 para el maestro (nodo con solo lectura =0) y el grupo de host 20 para los esclavos (solo lectura =1).
Como siguiente paso, necesitamos agregar un usuario de monitoreo en los nodos de MySQL para que ProxySQL pueda monitorearlos. Iremos con los valores predeterminados, idealmente cambiará las credenciales en ProxySQL.
mysql> SHOW VARIABLES LIKE 'mysql-monitor_username';
+------------------------+---------+
| Variable_name | Value |
+------------------------+---------+
| mysql-monitor_username | monitor |
+------------------------+---------+
1 row in set (0.00 sec)
mysql> SHOW VARIABLES LIKE 'mysql-monitor_password';
+------------------------+---------+
| Variable_name | Value |
+------------------------+---------+
| mysql-monitor_password | monitor |
+------------------------+---------+
1 row in set (0.00 sec)
Entonces, necesitamos crear el usuario 'monitor' con la contraseña 'monitor'. Para hacer eso, necesitaremos ejecutar la siguiente concesión en el servidor MySQL maestro:
mysql> create user [email protected]'%' identified by 'monitor';
Query OK, 0 rows affected (0.56 sec)
Volviendo a ProxySQL:tenemos que configurar los usuarios que usará nuestra aplicación para acceder a MySQL y las reglas de consulta, que están destinadas a brindarnos una división de lectura y escritura.
mysql> INSERT INTO mysql_users (username, password, default_hostgroup) VALUES ('sbtest', 'sbtest', 10);
Query OK, 1 row affected (0.34 sec)
mysql> INSERT INTO mysql_query_rules (rule_id,active,match_digest,destination_hostgroup,apply) VALUES (100, 1, '^SELECT.*FOR UPDATE$',10,1), (200,1,'^SELECT',20,1), (300,1,'.*',10,1);
Query OK, 3 rows affected (0.01 sec)
Tenga en cuenta que usamos la contraseña en el texto sin formato y confiaremos en ProxySQL para codificarla. En aras de la seguridad, debe pasar explícitamente aquí el hash de la contraseña de MySQL.
Finalmente, necesitamos aplicar todos los cambios.
mysql> LOAD MYSQL SERVERS TO RUNTIME;
Query OK, 0 rows affected (0.02 sec)
mysql> LOAD MYSQL USERS TO RUNTIME;
Query OK, 0 rows affected (0.01 sec)
mysql> LOAD MYSQL QUERY RULES TO RUNTIME;
Query OK, 0 rows affected (0.01 sec)
mysql> SAVE MYSQL SERVERS TO DISK;
Query OK, 0 rows affected (0.07 sec)
mysql> SAVE MYSQL QUERY RULES TO DISK;
Query OK, 0 rows affected (0.02 sec)
También queremos cargar las contraseñas cifradas desde el tiempo de ejecución:las contraseñas de texto sin formato se cifran cuando se cargan en la configuración del tiempo de ejecución, para mantenerlas en el disco necesitamos cargarlas desde el tiempo de ejecución y luego almacenarlas en el disco:
mysql> SAVE MYSQL USERS FROM RUNTIME;
Query OK, 0 rows affected (0.00 sec)
mysql> SAVE MYSQL USERS TO DISK;
Query OK, 0 rows affected (0.02 sec)
Esto es todo cuando se trata de ProxySQL. Antes de realizar más pasos, debe verificar si puede conectarse a servidores proxy desde sus servidores de aplicaciones.
[email protected]:~# mysql -h 10.0.0.103 -usbtest -psbtest -P6033 -e "SELECT * FROM sbtest.sbtest4 LIMIT 1\G"
mysql: [Warning] Using a password on the command line interface can be insecure.
*************************** 1. row ***************************
id: 1
k: 50147
c: 68487932199-96439406143-93774651418-41631865787-96406072701-20604855487-25459966574-28203206787-41238978918-19503783441
pad: 22195207048-70116052123-74140395089-76317954521-98694025897
En nuestro caso, todo se ve bien. Ahora es el momento de instalar Keepalived.
Instalación mantenida
La instalación es bastante simple (al menos en Ubuntu 16.04, que usamos):
apt install keepalived
Luego debe crear archivos de configuración para ambos servidores:
Nodo principal de mantenimiento:
vrrp_script chk_haproxy {
script "killall -0 haproxy" # verify the pid existance
interval 2 # check every 2 seconds
weight 2 # add 2 points of prio if OK
}
vrrp_instance VI_HAPROXY {
interface eth1 # interface to monitor
state MASTER
virtual_router_id 52 # Assign one ID for this route
priority 101
unicast_src_ip 10.0.0.103
unicast_peer {
10.0.0.104
}
virtual_ipaddress {
10.0.0.112 # the virtual IP
}
track_script {
chk_haproxy
}
# notify /usr/local/bin/notify_keepalived.sh
}
Copia de seguridad del nodo keepalive:
vrrp_script chk_haproxy {
script "killall -0 haproxy" # verify the pid existance
interval 2 # check every 2 seconds
weight 2 # add 2 points of prio if OK
}
vrrp_instance VI_HAPROXY {
interface eth1 # interface to monitor
state MASTER
virtual_router_id 52 # Assign one ID for this route
priority 100
unicast_src_ip 10.0.0.103
unicast_peer {
10.0.0.104
}
virtual_ipaddress {
10.0.0.112 # the virtual IP
}
track_script {
chk_haproxy
}
# notify /usr/local/bin/notify_keepalived.sh
Esto es todo, puede iniciar keepalive en ambos nodos:
service keepalived start
Debería ver información en los registros de que uno de los nodos ingresó al estado MAESTRO y que VIP se ha activado en ese nodo.
May 7 09:52:11 vagrant systemd[1]: Starting Keepalive Daemon (LVS and VRRP)...
May 7 09:52:11 vagrant Keepalived[26686]: Starting Keepalived v1.2.24 (08/06,2018)
May 7 09:52:11 vagrant Keepalived[26686]: Opening file '/etc/keepalived/keepalived.conf'.
May 7 09:52:11 vagrant Keepalived[26696]: Starting Healthcheck child process, pid=26697
May 7 09:52:11 vagrant Keepalived[26696]: Starting VRRP child process, pid=26698
May 7 09:52:11 vagrant Keepalived_healthcheckers[26697]: Initializing ipvs
May 7 09:52:11 vagrant Keepalived_vrrp[26698]: Registering Kernel netlink reflector
May 7 09:52:11 vagrant Keepalived_vrrp[26698]: Registering Kernel netlink command channel
May 7 09:52:11 vagrant Keepalived_vrrp[26698]: Registering gratuitous ARP shared channel
May 7 09:52:11 vagrant systemd[1]: Started Keepalive Daemon (LVS and VRRP).
May 7 09:52:11 vagrant Keepalived_vrrp[26698]: Unable to load ipset library
May 7 09:52:11 vagrant Keepalived_vrrp[26698]: Unable to initialise ipsets
May 7 09:52:11 vagrant Keepalived_vrrp[26698]: Opening file '/etc/keepalived/keepalived.conf'.
May 7 09:52:11 vagrant Keepalived_vrrp[26698]: Using LinkWatch kernel netlink reflector...
May 7 09:52:11 vagrant Keepalived_healthcheckers[26697]: Registering Kernel netlink reflector
May 7 09:52:11 vagrant Keepalived_healthcheckers[26697]: Registering Kernel netlink command channel
May 7 09:52:11 vagrant Keepalived_healthcheckers[26697]: Opening file '/etc/keepalived/keepalived.conf'.
May 7 09:52:11 vagrant Keepalived_healthcheckers[26697]: Using LinkWatch kernel netlink reflector...
May 7 09:52:11 vagrant Keepalived_vrrp[26698]: pid 26701 exited with status 256
May 7 09:52:12 vagrant Keepalived_vrrp[26698]: VRRP_Instance(VI_HAPROXY) Transition to MASTER STATE
May 7 09:52:13 vagrant Keepalived_vrrp[26698]: pid 26763 exited with status 256
May 7 09:52:13 vagrant Keepalived_vrrp[26698]: VRRP_Instance(VI_HAPROXY) Entering MASTER STATE
May 7 09:52:15 vagrant Keepalived_vrrp[26698]: pid 26806 exited with status 256
[email protected]:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:ee:87:c4 brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:feee:87c4/64 scope link
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:fc:ac:21 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.103/24 brd 10.0.0.255 scope global eth1
valid_lft forever preferred_lft forever
inet 10.0.0.112/32 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fefc:ac21/64 scope link
valid_lft forever preferred_lft forever
Como puede ver, en el nodo 10.0.0.103 se ha generado un VIP (10.0.0.112). Ahora podemos concluir moviendo el tráfico de la configuración anterior a la nueva.
Cambiar el tráfico a una configuración de ProxySQL
Hay muchos métodos sobre cómo hacerlo, depende principalmente de su entorno particular. Si usa DNS para mantener un dominio que apunta a su HAProxy VIP, puede hacer un cambio allí y, gradualmente, con el tiempo, todas las conexiones volverán a apuntar al nuevo VIP. También puede realizar un cambio en su aplicación, especialmente si los detalles de la conexión están codificados; una vez que implemente el cambio, los nodos comenzarán a conectarse a la nueva configuración. No importa cómo lo haga, sería genial probar la nueva configuración antes de realizar un cambio global. Seguro que lo probó en su entorno de prueba, pero no es una mala idea elegir un puñado de servidores de aplicaciones y redirigirlos al nuevo proxy, monitoreando cómo se ven en cuanto al rendimiento. A continuación se muestra un ejemplo simple que utiliza iptables, que puede ser útil para realizar pruebas.
En los hosts de ProxySQL, redirija el tráfico del host 10.0.0.11 y el puerto 3307 al host 10.0.0.112 y el puerto 6033:
iptables -t nat -A OUTPUT -p tcp -d 10.0.0.111 --dport 3307 -j DNAT --to-destination 10.0.0.112:6033
Dependiendo de su aplicación, es posible que deba reiniciar el servidor web u otros servicios (si su aplicación crea un conjunto constante de conexiones a la base de datos) o simplemente esperar a que se abran nuevas conexiones contra ProxySQL. Puede verificar que ProxySQL está recibiendo el tráfico:
mysql> show processlist;
+-----------+--------+--------+-----------+---------+---------+-----------------------------------------------------------------------------+
| SessionID | user | db | hostgroup | command | time_ms | info |
+-----------+--------+--------+-----------+---------+---------+-----------------------------------------------------------------------------+
| 12 | sbtest | sbtest | 20 | Sleep | 0 | |
| 13 | sbtest | sbtest | 10 | Query | 0 | DELETE FROM sbtest23 WHERE id=49957 |
| 14 | sbtest | sbtest | 10 | Query | 59 | DELETE FROM sbtest11 WHERE id=50185 |
| 15 | sbtest | sbtest | 20 | Query | 59 | SELECT c FROM sbtest8 WHERE id=46054 |
| 16 | sbtest | sbtest | 20 | Query | 0 | SELECT DISTINCT c FROM sbtest27 WHERE id BETWEEN 50115 AND 50214 ORDER BY c |
| 17 | sbtest | sbtest | 10 | Query | 0 | DELETE FROM sbtest32 WHERE id=50084 |
| 18 | sbtest | sbtest | 10 | Query | 26 | DELETE FROM sbtest28 WHERE id=34611 |
| 19 | sbtest | sbtest | 10 | Query | 16 | DELETE FROM sbtest4 WHERE id=50151 |
+-----------+--------+--------+-----------+---------+---------+-----------------------------------------------------------------------------+
Eso fue todo, hemos movido el tráfico de HAProxy a la configuración de ProxySQL. Tomó algunos pasos, pero definitivamente es factible con una interrupción muy pequeña en el servicio.
¿Cómo migrar de HAProxy a ProxySQL usando ClusterControl?
En la sección anterior, explicamos cómo implementar manualmente la configuración de ProxySQL y luego migrar a ella. En esta sección nos gustaría explicar cómo lograr el mismo objetivo usando ClusterControl. La configuración inicial es exactamente la misma, por lo que debemos continuar con la implementación de ProxySQL.
Implementación de ProxySQL mediante ClusterControl
La implementación de ProxySQL en ClusterControl es solo cuestión de unos pocos clics.
Implementar ProxySQL en ClusterControlTuvimos que elegir la IP o el nombre de host de un nodo, pasar las credenciales para el usuario administrativo de CLI y el usuario de monitoreo de MySQL. Decidimos usar MySQL existente y pasamos los detalles de acceso para el usuario 'sbtest'@'%' que usamos en la aplicación. Elegimos qué nodos queremos usar en el balanceador de carga, también aumentamos el retraso máximo de replicación (si se cruza ese umbral, ProxySQL no enviará el tráfico a ese esclavo) de 10 segundos predeterminados a 100, ya que ya estamos sufriendo por la replicación. retraso. Después de un rato, los nodos ProxySQL se agregarán al clúster.
Implementación de Keepalived para ProxySQL mediante ClusterControl
Cuando se han agregado nodos ProxySQL, es hora de implementar Keepalived.
Keepalived con ProxySQL en ClusterControlTodo lo que teníamos que hacer era elegir en qué nodos ProxySQL queremos que Keepalived se implemente, la IP virtual y la interfaz a la que se vinculará VIP. Cuando se complete la implementación, cambiaremos el tráfico a la nueva configuración utilizando uno de los métodos mencionados en la sección anterior "Cambiar el tráfico a la configuración de ProxySQL".
Supervisión del tráfico de ProxySQL en ClusterControlPodemos verificar que el tráfico ha cambiado a ProxySQL observando el gráfico de carga; como puede ver, la carga está mucho más distribuida entre los nodos del clúster. También puede verlo en el siguiente gráfico, que muestra la distribución de consultas en el clúster.
Panel ProxySQL en ClusterControlFinalmente, el tablero de ProxySQL también muestra que el tráfico se distribuye entre todos los nodos del clúster:
Panel ProxySQL en ClusterControlEsperamos que se beneficie de esta publicación de blog, como puede ver, con ClusterControl, la implementación de la nueva arquitectura toma solo un momento y requiere solo unos pocos clics para que todo funcione. Cuéntanos tu experiencia en este tipo de migraciones.