Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Balanceamento de carga com reconhecimento de banco de dados:como migrar do HAProxy para o ProxySQL


HAProxy e ProxySQL são balanceadores de carga muito populares no mundo MySQL, mas há uma diferença significativa entre ambos os proxies. Não entraremos em detalhes aqui, você pode ler mais sobre HAProxy no Tutorial HAProxy e ProxySQL no Tutorial ProxySQL. A diferença mais importante é que o ProxySQL é um proxy com reconhecimento de SQL, ele analisa o tráfego e entende o protocolo MySQL e, como tal, pode ser usado para modelagem avançada de tráfego - você pode bloquear consultas, reescrevê-las, direcioná-las para hosts específicos, armazenar em cache eles e muitos mais. O HAProxy, por outro lado, é um proxy de camada 4 muito simples, porém eficiente, e tudo o que ele faz é enviar pacotes para o back-end. O ProxySQL pode ser usado para executar uma divisão de leitura e gravação - ele entende o SQL e pode ser configurado para detectar se uma consulta é SELECT ou não e roteá-la de acordo:SELECTs para todos os nós, outras consultas apenas para master. Esse recurso não está disponível no HAProxy, que precisa usar duas portas  separadas e dois back-ends separados para mestre e escravos. A divisão de leitura e gravação deve ser realizada no lado do aplicativo.

Por que migrar para ProxySQL?


Com base nas diferenças que explicamos acima, diríamos que a principal razão pela qual você pode querer mudar de HAProxy para ProxySQL é a falta da divisão de leitura e gravação no HAProxy. Se você usa um cluster de bancos de dados MySQL e não importa se é uma replicação assíncrona ou um Galera Cluster, você provavelmente deseja dividir leituras de gravações. Para a replicação do MySQL, obviamente, essa seria a única maneira de utilizar seu cluster de banco de dados, pois as gravações sempre precisam ser enviadas ao mestre. Portanto, se você não puder fazer a divisão de leitura e gravação, poderá enviar consultas apenas para o mestre. Para Galera, a divisão de leitura e gravação não é obrigatória, mas definitivamente boa de se ter. Claro, você pode configurar todos os nós Galera como um back-end no HAProxy e enviar tráfego para todos eles no modo round-robin, mas isso pode resultar em gravações de vários nós conflitantes entre si, levando a deadlocks e queda de desempenho. Também vimos problemas e bugs no cluster Galera, para os quais, até que fossem corrigidos, a solução alternativa era direcionar todas as gravações para um único nó. Assim, a melhor prática é enviar todas as gravações para um nó Galera, pois isso leva a um comportamento mais estável e a um melhor desempenho.

Outra razão muito boa para a migração para ProxySQL é a necessidade de ter um melhor controle sobre o tráfego. Com o HAProxy você não pode fazer nada - ele apenas envia o tráfego para seus backends. Com o ProxySQL, você pode moldar seu tráfego usando regras de consulta (correspondência de tráfego usando expressões regulares, usuário, esquema, host de origem e muito mais). Você pode redirecionar OLAP SELECTs para escravo de análise (isso vale tanto para replicação quanto para Galera). Você pode descarregar seu mestre redirecionando alguns dos SELECTs dele. Você pode implementar o firewall SQL. Você pode adicionar um atraso a algumas das consultas, você pode matar as consultas se elas demorarem mais do que um tempo predefinido. Você pode reescrever consultas para adicionar dicas do otimizador. Tudo isso não é possível com HAProxy.

Como migrar do HAProxy para o ProxySQL?


Primeiro, vamos considerar a seguinte topologia...
ClusterControl MySQL Topologia MySQL Replication Cluster in ClusterControl
Temos aqui um cluster de replicação composto por um mestre e dois escravos. Temos dois nós HAProxy implantados, cada um usa dois back-ends - na porta 3307 para mestre (gravações) e 3308 para todos os nós (leituras). Keepalived é usado para fornecer um IP virtual nessas duas instâncias HAProxy - se uma delas falhar, outra será usada. Nosso aplicativo se conecta diretamente ao VIP, por meio dele a uma das instâncias do HAProxy. Vamos supor que nosso aplicativo (vamos usar o Sysbench) não pode fazer a divisão de leitura e gravação, portanto, temos que nos conectar ao backend "gravador". Como resultado, a maior parte da carga está em nosso mestre (10.0.0.101).

Quais seriam as etapas para migrar para o ProxySQL? Vamos pensar sobre isso por um momento. Primeiro, temos que implantar e configurar o ProxySQL. Teremos que adicionar servidores ao ProxySQL, criar usuários de monitoramento necessários e criar regras de consulta adequadas. Por fim, teremos que implantar o Keepalived em cima do ProxySQL, criar outro IP virtual e, em seguida, garantir a mudança mais perfeita possível para nosso aplicativo de HAProxy para ProxySQL .

Vamos ver como podemos fazer isso...

Como instalar o ProxySQL


Pode-se instalar o ProxySQL de várias maneiras. Você pode usar o repositório, seja do próprio ProxySQL (https://repo.proxysql.com) ou se você usar o Percona XtraDB Cluster, você também pode instalar o ProxySQL do repositório Percona, embora possa exigir alguma configuração adicional, pois depende da CLI ferramentas administrativas criadas para PXC. Dado que estamos falando de replicação, usá-los pode tornar as coisas mais complexas. Finalmente, você também pode instalar os binários do ProxySQL depois de baixá-los do ProxySQL GitHub. Atualmente existem duas versões estáveis, 1.4.xe 2.0.x. Existem diferenças entre o ProxySQL 1.4 e o ProxySQL 2.0 em termos de recursos, para este blog vamos nos ater ao branch 1.4.x, pois é melhor testado e o conjunto de recursos é suficiente para nós.

Usaremos o repositório ProxySQL e implantaremos o ProxySQL em dois nós adicionais:10.0.0.103 e 10.0.0.104.

Primeiro, instalaremos o ProxySQL usando o repositório oficial. Também garantiremos que o cliente MySQL esteja instalado (nós o usaremos para configurar o ProxySQL). Lembre-se de que o processo pelo qual passamos não é de nível de produção. Para produção, você desejará pelo menos alterar as credenciais padrão para o usuário administrativo. Você também desejará revisar a configuração e garantir que ela esteja de acordo com suas expectativas e 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

Agora, como o ProxySQL foi iniciado, usaremos a CLI para configurar o ProxySQL.
mysql -uadmin -padmin -P6032 -h127.0.0.1

Primeiro, definiremos servidores de back-end e grupos de hosts de replicação:
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)

Temos três servidores, também definimos que o ProxySQL deve usar hostgroup 10 para master (nó com read_only=0) e hostgroup 20 para slaves (read_only=1).

Como próximo passo, precisamos adicionar um usuário de monitoramento nos nós MySQL para que o ProxySQL possa monitorá-los. Iremos com os padrões, idealmente você alterará as credenciais no 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)

Então, precisamos criar o usuário ‘monitor’ com a senha ‘monitor’. Para fazer isso, precisaremos executar a seguinte concessão no servidor MySQL mestre:
mysql> create user [email protected]'%' identified by 'monitor';
Query OK, 0 rows affected (0.56 sec)

De volta ao ProxySQL - temos que configurar os usuários que nosso aplicativo usará para acessar o MySQL e as regras de consulta, que se destinam a nos fornecer uma divisão de leitura e gravação.
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)

Observe que usamos a senha no texto simples e contaremos com o ProxySQL para fazer o hash. Por uma questão de segurança, você deve passar aqui explicitamente o hash de senha do MySQL.

Por fim, precisamos aplicar todas as alterações.
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)

Também queremos carregar as senhas com hash do tempo de execução:as senhas de texto simples são criptografadas quando carregadas na configuração do tempo de execução, para mantê-las em disco, precisamos carregá-las do tempo de execução e depois armazená-las no 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)

É isso quando se trata de ProxySQL. Antes de fazer outras etapas, você deve verificar se pode se conectar a proxies de seus servidores de aplicativos.
[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

No nosso caso, tudo parece bem. Agora é hora de instalar o Keepalived.

Instalação mantida


A instalação é bastante simples (pelo menos no Ubuntu 16.04, que usamos):
apt install keepalived

Então você tem que criar arquivos de configuração para ambos os servidores:

Nó mestre keepalived:
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
}

Backup do nó 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

É isso, você pode iniciar o keepalived em ambos os nós:
service keepalived start

Você deve ver informações nos logs de que um dos nós entrou no estado MASTER e que o VIP foi criado nesse nó.
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 você pode ver, no nó 10.0.0.103 um VIP (10.0.0.112) foi gerado. Agora podemos concluir movendo o tráfego da configuração antiga para a nova.

Mudando o tráfego para uma configuração ProxySQL


Existem muitos métodos de como fazê-lo, depende principalmente do seu ambiente específico. Se acontecer de você usar o DNS para manter um domínio apontando para o seu HAProxy VIP, , basta fazer uma alteração lá e, gradualmente, com o tempo, todas as conexões irão apontar para o novo VIP. Você também pode fazer uma alteração em seu aplicativo, especialmente se os detalhes da conexão estiverem codificados - assim que você implementar a alteração, os nós começarão a se conectar à nova configuração. Não importa como você faça isso, seria ótimo testar a nova configuração antes de fazer uma mudança global. Você com certeza testou em seu ambiente de teste, mas não é uma má ideia escolher alguns servidores de aplicativos e redirecioná-los para o novo proxy, monitorando a aparência deles em termos de desempenho. Abaixo está um exemplo simples utilizando iptables, que pode ser útil para testes.

Nos hosts ProxySQL, redirecione o tráfego do host 10.0.0.11 e da porta 3307 para o host 10.0.0.112 e a porta 6033:
iptables -t nat -A OUTPUT -p tcp -d 10.0.0.111 --dport 3307 -j DNAT --to-destination 10.0.0.112:6033

Dependendo do seu aplicativo, pode ser necessário reiniciar o servidor da Web ou outros serviços (se seu aplicativo criar um pool constante de conexões com o banco de dados) ou apenas aguardar que novas conexões sejam abertas no ProxySQL. Você pode verificar se o ProxySQL está recebendo o tráfego:
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                                          |
+-----------+--------+--------+-----------+---------+---------+-----------------------------------------------------------------------------+

Foi isso, movemos o tráfego do HAProxy para a configuração do ProxySQL. Foram necessários alguns passos, mas é definitivamente possível com uma interrupção muito pequena no serviço.

Como migrar do HAProxy para o ProxySQL usando o ClusterControl?


Na seção anterior, explicamos como implantar manualmente a configuração do ProxySQL e depois migrar para ela. Nesta seção, gostaríamos de explicar como atingir o mesmo objetivo usando o ClusterControl. A configuração inicial é exatamente a mesma, portanto, precisamos prosseguir com a implantação do ProxySQL.

Implantando ProxySQL usando ClusterControl


A implantação do ProxySQL no ClusterControl é apenas uma questão de alguns cliques.
Implantar ProxySQL no ClusterControl
Tivemos que escolher o IP ou o nome do host de um nó, passar as credenciais para o usuário administrativo da CLI e o usuário de monitoramento do MySQL. Decidimos usar o MySQL existente e passamos detalhes de acesso para o usuário ‘sbtest’@’%’ que usamos no aplicativo. Escolhemos quais nós queremos usar no balanceador de carga, também aumentamos o atraso máximo de replicação (se esse limite for ultrapassado, o ProxySQL não enviará o tráfego para esse escravo) do padrão 10 segundos para 100, pois já estamos sofrendo com a replicação atraso. Após algum tempo, os nós ProxySQL serão adicionados ao cluster.

Implantando Keepalived para ProxySQL usando ClusterControl


Quando os nós ProxySQL forem adicionados, é hora de implantar o Keepalived.
Mantido com ProxySQL no ClusterControl
Tudo o que tivemos que fazer é escolher em quais nós ProxySQL queremos que o Keepalived implante, IP virtual e interface à qual o VIP será vinculado. Quando a implantação for concluída, mudaremos o tráfego para a nova configuração usando um dos métodos mencionados na seção "Mudando o tráfego para a configuração do ProxySQL" acima.
Monitorando o tráfego ProxySQL no ClusterControl
Podemos verificar se o tráfego mudou para ProxySQL observando o gráfico de carga - como você pode ver, a carga é muito mais distribuída entre os nós do cluster. Você também pode vê-lo no gráfico abaixo, que mostra a distribuição das consultas no cluster.
ProxySQL Dashboard no ClusterControl
Por fim, o painel ProxySQL também mostra que o tráfego é distribuído por todos os nós do cluster:
ProxySQL Dashboard no ClusterControl
Esperamos que você se beneficie desta postagem no blog, como você pode ver, com o ClusterControl, a implantação da nova arquitetura leva apenas um momento e requer apenas alguns cliques para que as coisas funcionem. Conte-nos sobre sua experiência em tais migrações.