ProxySQL - uma ferramenta para desmultiplexar conexões

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.

imagem

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.

imagem

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.

imagem

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/documentation

Agradecemos sua atenção.

Nossa configuração, com a qual resolvemos o problema descrito acima, veja abaixo.

Nossa configuração

datadir="/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,
  })

All Articles