Olá, meu nome é Alexander Yakovlev, trabalho na Citimobil e opero. Hoje vou falar sobre um produto muito interessante ProxySQL - é um MySQL Proxy de alto desempenho que pode fazer muitas coisas - capturar e matar solicitações por máscara, com ele você pode procurar por injeção de sql, duplicar a carga e muito mais. Vou falar sobre a nossa experiência com ele.Mais cedo ou mais tarde, qualquer grande projeto de TI, cujo desenvolvimento começou com um par de servidores, encontrará a situação descrita abaixo. Imagine que o projeto inicialmente tivesse apenas um banco de dados - o servidor mestre. Gradualmente, um monte de escravos foram adicionados a ele. Então eles introduziram o sharding.E um belo dia, a carga aumenta repentinamente 10 vezes. Por exemplo, porque seu principal concorrente caiu e os clientes correram para você. Neste ponto, parece-lhe que você pode simplesmente escalar a carga adicionando servidores da web. Mas depois de fazer isso, surge uma situação desagradável.Considere o exemplo de um assistente. Digamos que você tenha 50 servidores da Web e a cada 200 processos de php-fpm. Então 50 * 200 conexões chegarão ao mestre, e 50 * 200 / número de escravos chegarão a cada escravo (se, é claro, o roundrobin estiver configurado em haproxy) - veja a figura abaixo. Obviamente, 10 mil conexões com o mestre são muitas, mas ainda suportáveis, e se houver 200 sites, o número de conexões será ainda maior e uma conexão = um encadeamento.Foi nesse gargalo que encontramos.
Então começamos a discutir: a conexão com o assistente está sempre instalada no código, mas é necessária para todos os processos fpm? Provavelmente não. Percebemos que um grande número de conexões persistentes com o mestre simplesmente fica suspenso. E eles decidiram que precisamos de desmultiplexação.
Para isso, chamamos a atenção para um produto chamado ProxySQL. Funciona como um proxy reverso normal: as conexões são estabelecidas e redistribui o tráfego de acordo com certas regras especificadas na configuração.Instalamos o ProxySQL em todos os nossos servidores da web e, na configuração do aplicativo, especificamos que a chamada para o banco de dados mestre é realizada no endereço 127.0.0.1. Se antes de 200 funcionários do FPM em cada servidor da Web significavam 200 conexões com a base mestre dessa máquina, agora a situação mudou. Essas 200 conexões são fornecidas no ProxySQL e 50-70 são desativadas em momentos diferentes. Ou seja, o ProxySQL pode reutilizar conexões existentes.Graças à desmultiplexação, reduzimos o número de conexões de 3 a 10 vezes em todos os mestres, veja o gráfico de conexões atuais de um dos mestres abaixo.
Graças ao ProxySQL, nos livramos do gargalo acima. Mas este não é o único fluxo de trabalho que aprimoramos com esta ferramenta.Ainda não concluímos o segundo processo, mas estamos muito próximos da conclusão. Usando o ProxySQL, planejamos duplicar a carga real no ambiente de teste. Isso é necessário para verificar novos recursos com o tráfego de combate.Como isso será implementado? O aplicativo vai para o ProxySQL e envia tráfego por duas rotas: para os bancos de dados de batalha para o aplicativo funcionar e para o ambiente de teste para verificar novos recursos sob carga.Um recurso do ProxySQL é que existe sua configuração, que no nosso caso é implementada através do puppet (para o puppet existe um módulo ProxySQL), mas também existe o conceito de zona de tempo de execução quando, para fazer uma alteração (adicionar servidor, adicionar usuário, excluir servidor e usuário) ), você não precisa reiniciar / recarregar normalmente. Tudo é feito através do console ProxySQL, por exemplo, como este.mysql -ulogin -ppassword -h 127.0.0.1 -P6032 -e "INSERT INTO mysql_users(username,password,default_hostgroup) VALUES ('sm_username','pass',1);;LOAD MYSQL USERS TO RUNTIME;SAVE MYSQL USERS TO DISK;"
Em mais detalhes, é claro, na documentação oficial proxysql.com/documentationAgradecemos sua atenção.Nossa configuração, com a qual resolvemos o problema descrito acima, veja abaixo.Nossa configuraçãodatadir="/var/lib/proxysql"
admin_variables=
{
admin_credentials="user:pass"
mysql_ifaces="0.0.0.0:6032"
refresh_interval=2000
web_enabled=true
web_port=6080
stats_credentials="stats:admin"
}
mysql_variables =
{
threads = 1000
max_connections = 2000
default_query_delay= 0
default_query_timeout=1
have_compress=true
poll_timeout=2000
interfaces="0.0.0.0:6033;/tmp/proxysql.sock"
default_schema="information_schema"
stacksize=1048576
server_version="5.7.22"
connect_timeout_server=10000
monitor_history=60000
monitor_connect_interval=200000
monitor_ping_interval=200000
ping_interval_server_msec=5000
ping_timeout_server=200
commands_stats=true
sessions_sort=true
monitor_username="root"
monitor_password="password"
monitor_galera_healthcheck_interval=200
monitor_galera_healthcheck_timeout=80
}
mysql_servers =
(
{
address = "ip_real_mysql_server",
port = 3306,
max_connections = 10000,
host_group = 1,
})
mysql_users =
(
{
username = "user",
password = "pass",
default_hostgroup = 1,
transaction_persistent = 0,
active = 1,
})