Eu tenho um cluster Galera Replication com três nós MariaDB onde um cluster Maxscale Active-Passive na frente fornece uma imagem de nó único para clientes tis.
Eu tenho um cliente de mau comportamento, que abre conexões e não as fecha. O número de conexões continua aumentando até que os limites do banco de dados sejam atingidos. Para limitar o número de conexões que configurei abaixo de dois parâmetros
max_connections=
max_user_connections=
Minha situação é essa, quando tenho apenas max_connections configurados, sempre que os limites são atingidos o nó Galera deixa de aceitar mais conexão com erro de "Too many connections". Quando o Maxscale vê essas rejeições de conexão n vezes, ele coloca o servidor em modo de manutenção . Eu posso entender esse comportamento, é esperado. Quando configuro max_user_connections, e porque o aplicativo está se comportando mal e tentando fazer novas conexões continuamente, quando o limite específico do usuário atinge mais tentativas de conexões falham nos nós mariadb no backend. O Maxscale observa essas falhas e novamente coloca o servidor no modo Manutenção . Acredito que durante esse tempo ele veja apenas tentativas de conexão do cliente ruim, nenhum outro aplicativo tentou se conectar.
E desta forma, MaxScale coloca todos os três nós no modo de Manutenção ao longo do tempo, o que torna o serviço DB completo indisponível.
Para mim como administrador, a situação se torna a mesma, colocar um limite específico de usuário não alcança nada. Eu gostaria de perguntar dois pontos aqui
Q1. Como posso evitar que apenas uma falha de conexão de usuário coloque o nó mariadb de back-end em manutenção?
Q2. Alguma documentação, ou tutoriais, referência de artigo sobre como e quando MaxScale decide colocar um servidor em modo de manutenção?
Abaixo estão os detalhes sobre o ambiente
Galera - 25.3.23, MariaDB - 10.3.12, MaxScale - 2.4.11, OS - RHEL 7.4 (Maipo)
Aqui está minha configuração
Configuração da Galeria MariaDB
[server]
# this is only for the mysqld standalone daemon
[mysqld]
#user statistics
userstat=1
performance_schema
#wait_timeout=600
max_allowed_packet=1024M
#
lower_case_table_names=1
#
max_connections=1500
max_user_connections=200
#
# * Galera-related settings
#
[galera]
# Mandatory settings
wsrep_on=ON
wsrep_provider=/usr/lib64/galera/libgalera_smm.so
wsrep_provider_options="gcache.size=300M; gcache.page_size=300M; pc.ignore_sb=false; pc.ignore_quorum=false"
#wsrep_cluster_address defines members of the cluster
wsrep_cluster_address=gcomm://x.x.x.1,x.x.x.2,x.x.x.3
wsrep_cluster_name="mariadb-cluster"
wsrep_node_address=x.x.x.1
wsrep_node_incoming_address=x.x.x.1
wsrep_debug=OFF
#
binlog_format=row
default_storage_engine=InnoDB
innodb_autoinc_lock_mode=2
innodb_doublewrite=1
query_cache_size=0
innodb_flush_log_at_trx_commit=0
innodb_buffer_pool_size=5G
#
bind-address=x.x.x.1
#
[mariadb]
#performance
wait_timeout=31536000
#
#query logging
log_output=FILE
#slow queries
slow_query_log
slow_query_log_file=/var/log/mariadb/mariadb-slow.log
long_query_time=10.0
log_queries_not_using_indexes=ON
min_examined_row_limit=1000
log_slow_rate_limit=1
log_slow_verbosity=query_plan,explain
#
#error logs
log_error=/var/log/mariadb/mariadb-error.log
log_warnings=2
Da mesma forma, todos os três nós Galera são configurados.
Configuração MaxScale
[maxscale]
threads=auto
# Server definitions
[mariadb1]
type=server
address=x.x.x.1
port=3306
protocol=MariaDBBackend
#priority=0
[mariadb2]
type=server
address=x.x.x.2
port=3306
protocol=MariaDBBackend
#priority=1
[mariadb3]
type=server
address=x.x.x.3
port=3306
protocol=MariaDBBackend
#priority=1
# Monitor for the servers
#
[Galera-Monitor]
type=monitor
module=galeramon
servers=mariadb1, mariadb2, mariadb3
user=xxx
password=xxx
#disable_master_role_setting=true
monitor_interval=1000
#use_priority=true
#
disable_master_failback=true
available_when_donor=true
# Service definitions
[Galera-Service]
type=service
router=readwritesplit
master_accept_reads=true
connection_keepalive=300s
master_reconnection=true
master_failure_mode=error_on_write
connection_timeout=3600s
servers=mariadb1, mariadb2, mariadb3
user=xxx
password=xxx
#filters=Query-Log-Filter
#Listener
[Galera-Listener]
type=listener
service=Galera-Service
protocol=MariaDBClient
port=4306
Não acho que MaxScale seja o componente que você deseja usar para corrigir esse problema. É possível fazer isso no próprio servidor MariaDB. Eu experimentei exatamente o mesmo problema e o resolvi impondo limites aos usuários do banco de dados usando a
max_user_connections
configuração.Por que esse valor é tão grande? Seus aplicativos mantêm as conexões abertas em vez de criar novas? Embora isso possa parecer uma boa ideia, significa que as conexões deixadas acidentalmente abertas/ociosas não serão fechadas até muito mais tarde.
Eu não acho que isso é correto.
Se você limitar os usuários do banco de dados para que a soma de
max_user_connection
para todos os usuários <max_connections
para cada um dos nós, os usuários não poderão atingir omax_connections
limite.Eu não acho que haja um único documento para isso, mas está espalhado pela documentação do MaxScale. Acho que o modo de manutenção começou como uma maneira de o administrador agendar o tempo de inatividade planejado, mas desde então também foi usado para outras coisas, veja, por exemplo, maintenance_on_low_disk_space
Eu tentei
connection_timeout, max_connections, max_user_connections
configurações nos nós do servidor de banco de dados, mas não ajudou. Quando o aplicativo inválido está fazendo tentativas de conexão e atinge o limite, os servidores de banco de dados descartam as conexões com"Too many connections"
. Maxscale observa isso por algum tempo e coloca os servidores de back-end emMaintenance
. A configuraçãomax_users_connections
para algum valor, digamos: 200, faz com que o servidor de back-end rejeite conexões quando o limite atinge um único usuário. Agora, quando houver váriasToo many connections
falhas devido ao estado 'max_users_connectionslimit threshold breach due to bad application, Maxscale again marks the server in
Maintenance'. Não diferencia que as tentativas sejam de um único usuário ou de muitos usuários coletivamente. Ele apenas vê as falhas 'Muitas conexões' do servidor.Para resolver a situação, criei um serviço separado em Maxscale para o aplicativo de mau comportamento com o
max_connections
limite definido. Criou um listener separado em um número de porta diferente para o serviço.Devido a um serviço separado, sempre que o
max_connections
limite atinge em MAxscale, outros clientes não são afetados. Além disso, cuidou para que omax_connections
limite nos servidores MariadB no back-end fosse maior do que o valor configurado no Maxscale, para que o limite atinja mais cedo no Maxscale e nunca coloque os servidores back-end noMaintenance mode
. O novo bloco de configuração para Maxscale é como abaixo -