At have en load balancer eller omvendt proxy foran din MySQL- eller MariaDB-server tilføjer en lille smule kompleksitet til din databaseopsætning, hvilket kan føre til, at nogle ting opfører sig anderledes. Teoretisk set burde en load balancer som sidder foran MySQL-servere (for eksempel en HAProxy foran en Galera Cluster) bare fungere som en forbindelsesmanager og distribuere forbindelserne til backend-serverne i henhold til en eller anden balanceringsalgoritme. MySQL har på den anden side sin egen måde at administrere klientforbindelser på. Ideelt set ville vi være nødt til at konfigurere disse to komponenter sammen for at undgå uventet adfærd og indsnævre fejlfindingsoverfladen ved fejlfinding af problemer.
Hvis du har en sådan opsætning, er det vigtigt at forstå disse komponenter, da de kan påvirke den overordnede ydeevne af din databasetjeneste. I dette blogindlæg vil vi dykke ned i MySQL's max_connections og HAProxy maxconn muligheder hhv. Bemærk, at timeout er en anden vigtig parameter, som vi bør vide, men det vil vi dække i et separat indlæg.
MySQL's Max Connections
Relaterede ressourcer MySQL-belastningsbalancering med HAProxy - Selvstudie Webinar Replay og Q&A:hvordan man implementerer og administrerer ProxySQL, HAProxy og MaxScale Webinar Replay &Slides:Hvordan man bygger skalerbare databaseinfrastrukturer med MariaDB &HAProxyAntallet af forbindelser, der er tilladt til en MySQL-server, styres af max_connections systemvariabel. Standardværdien er 151 (MySQL 5.7).
For at bestemme et godt tal for max_connections , de grundlæggende formler er:
Hvor,
**Variabel innodb_additional_mem_pool_size er fjernet i MySQL 5.7.4+. Hvis du kører i den ældre version, skal du tage højde for denne variabel.
Og,
Ved at bruge ovenstående formler kan vi beregne en passende max_connections værdi for denne særlige MySQL-server. For at starte processen skal du stoppe alle forbindelser fra klienter og genstarte MySQL-serveren. Sørg for, at du kun har det mindste antal processer, der kører på det bestemte tidspunkt. Du kan bruge 'mysqladmin' eller 'VIS PROCESSLISTE' til dette formål:
$ mysqladmin -uroot -p processlist
+--------+------+-----------+------+---------+------+-------+------------------+----------+
| Id | User | Host | db | Command | Time | State | Info | Progress |
+--------+------+-----------+------+---------+------+-------+------------------+----------+
| 232172 | root | localhost | NULL | Query | 0 | NULL | show processlist | 0.000 |
+--------+------+-----------+------+---------+------+-------+------------------+----------+
1 row in set (0.00 sec)
Fra ovenstående output kan vi fortælle, at kun én bruger er forbundet til MySQL-serveren, som er root. Hent derefter værtens tilgængelige RAM (i MB) (se under kolonnen 'tilgængelig'):
$ free -m
total used free shared buff/cache available
Mem: 3778 1427 508 148 1842 1928
Swap: 2047 4 2043
Blot for informationen giver kolonnen 'tilgængelig' et skøn over, hvor meget hukommelse der er tilgængelig til at starte nye applikationer uden at bytte (kun tilgængelig i kerne 3.14+).
Angiv derefter den tilgængelige hukommelse, 1928 MB i følgende sætning:
mysql> SELECT ROUND((1928 - (ROUND((@@innodb_buffer_pool_size + @@innodb_log_buffer_size + @@query_cache_size + @@tmp_table_size + @@key_buffer_size) / 1024 / 1024))) / (ROUND(@@read_buffer_size + @@read_rnd_buffer_size + @@sort_buffer_size + @@thread_stack + @@join_buffer_size + @@binlog_cache_size) / 1024 / 1024)) AS 'Possible Max Connections';
+--------------------------+
| Possible Max Connections |
+--------------------------+
| 265 |
+--------------------------+
**Variabel innodb_additional_mem_pool_size er fjernet i MySQL 5.7.4+. Hvis du kører i den ældre version, skal du tage højde for denne variabel.
Fra dette eksempel kan vi have op til 265 MySQL-forbindelser samtidigt i henhold til den tilgængelige RAM, værten har. Det giver ikke mening at konfigurere en højere værdi end det. Tilføj derefter følgende linje i MySQL-konfigurationsfilen under [mysqld]-direktivet:
max_connections = 265
Genstart MySQL-tjenesten for at anvende ændringen. Når det samlede antal samtidige forbindelser når 265, vil du få en "For mange forbindelser"-fejl, når du forsøger at oprette forbindelse til mysqld-serveren. Det betyder, at alle tilgængelige forbindelser er i brug af andre klienter. MySQL tillader faktisk max_connections +1 klienter for at forbinde. Den ekstra forbindelse er reserveret til brug af konti, der har SUPER-privilegiet. Så hvis du står over for denne fejl, bør du prøve at få adgang til serveren som en root-bruger (eller enhver anden SUPER-bruger) og se på proceslisten for at starte fejlfindingen.
HAProxy's Max Connections
HAProxy har 3 typer af max-forbindelser (maxconn) - global, defaults/listen og default-server. Antag, at en HAProxy-instans konfigureret med to lyttere, en til multi-writer-lytning på port 3307 (forbindelser distribueres til alle backend MySQL-servere) og en anden er single-writer på port 3308 (forbindelser videresendes til en enkelt MySQL-server):
global
...
maxconn 2000 #[a]
...
defaults
...
maxconn 3 #[b]
...
listen mysql_3307
...
maxconn 8 #[c]
balance leastconn
default-server port 9200 maxqueue 10 weight 10 maxconn 4 #[d]
server db1 192.168.55.171 check
server db2 192.168.55.172 check
server db3 192.168.55.173 check
listen mysql_3308
...
default-server port 9200 maxqueue 10 weight 10 maxconn 5 #[e]
server db1 192.168.55.171 check
server db2 192.168.55.172 check backup #[f]
Lad os se på betydningen af nogle af konfigurationslinjerne:
global.maxconn [a]
Det samlede antal samtidige forbindelser, der har tilladelse til at oprette forbindelse til denne HAProxy-instans. Normalt er denne værdi den højeste værdi af alle. I dette tilfælde vil HAProxy acceptere maksimalt 2000 forbindelser ad gangen og distribuere dem til alle lyttere, der er defineret i HAProxy-processen eller arbejder (du kan køre flere HAProxy-processer ved hjælp af nbproc mulighed).
HAProxy stopper med at acceptere forbindelser, når denne grænse er nået. Parameteren "ulimit-n" justeres automatisk til denne værdi. Da sockets anses for at være ækvivalente med filer fra systemperspektivet, er standardgrænsen for filbeskrivelser ret lille. Du vil sandsynligvis hæve standardgrænsen ved at indstille kernen til filbeskrivelser.
defaults.maxconn [b]
Standardværdi for maksimal forbindelse for alle lyttere. Det giver ikke mening, hvis denne værdi er højere end global.maxconn .
Hvis "maxconn"-linjen mangler under "lyt"-strofen (listen.maxconn ), vil lytteren adlyde denne værdi. I dette tilfælde vil mysql_3308 listener få maksimalt 3 forbindelser ad gangen. For at være sikker skal du indstille denne værdi til global.maxconn , divideret med antallet af lyttere. Men hvis du gerne vil prioritere andre lyttere for at få flere forbindelser, så brug listen.maxconn i stedet.
listen.maxconn [c]
De maksimalt tilladte forbindelser for den tilsvarende lytter. Lytteren har forrang over defaults.maxconn hvis specificeret. Det giver ikke mening, hvis denne værdi er højere end global.maxconn .
For en retfærdig fordeling af forbindelser til backend-servere som i tilfældet med en multi-writer-lytter (mysql_3307), skal du indstille denne værdi som listen.default-server.maxconn gange med antallet af backend-servere. I dette eksempel bør en bedre værdi være 12 i stedet for 8 [c]. Hvis vi vælger at holde fast i denne konfiguration, forventes db1 og db2 at modtage maksimalt 3 forbindelser hver, mens db3 maksimalt vil modtage 2 forbindelser (pga. balancering af leastconn), hvilket svarer til 8 forbindelser i alt. Det vil ikke ramme grænsen som angivet i [d].
For single-writer listener (mysql_3308), hvor forbindelser skal allokeres til én og kun én backend-server ad gangen, skal denne værdi indstilles til at være den samme eller højere end listen.default-server.maxconn .
listen.default-server.maxconn [d][e]
Dette er det maksimale antal forbindelser, som hver backend-server kan modtage ad gangen. Det giver ikke mening, hvis denne værdi er højere end listen.maxconn eller defaults.maxconn . Denne værdi skal være lavere eller lig med MySQL's max_connections variabel. Ellers risikerer du at udtømme forbindelserne til backend MySQL-serveren, især når MySQL's timeoutvariabler er konfigureret lavere end HAProxys timeouts.
I dette eksempel har vi indstillet hver MySQL-server til kun at få maksimalt 4 forbindelser ad gangen for multi-writer Galera noder [d]. Mens single-writer Galera-knuden maksimalt vil få 3 forbindelser ad gangen, på grund af den grænse, der gælder fra [b]. Da vi specificerede "backup" [f] til den anden node, vil den aktive node på én gang få alle 3 forbindelser allokeret til denne lytter.
Ovenstående forklaring kan illustreres i følgende diagram:
For at opsummere forbindelsesfordelingen forventes db1 at få et maksimalt antal på 6 forbindelser (3 fra 3307 + 3 fra 3308). db2 vil få 3 forbindelser (medmindre hvis db1 går ned, hvor den får yderligere 3), og db3 vil holde sig til 2 forbindelser uanset topologiændringer i klyngen.
Forbindelsesovervågning med ClusterControl
Med ClusterControl kan du overvåge MySQL- og HAProxy-forbindelsesbrug fra brugergrænsefladen. Følgende skærmbillede giver en oversigt over MySQL-forbindelsesrådgiveren (ClusterControl -> Performance -> Advisors), hvor den overvåger de aktuelle og nogensinde brugte MySQL-forbindelser for hver server i klyngen:
For HAProxy integrerer ClusterControl med HAProxy-statistiksiden for at indsamle metrics. Disse præsenteres under fanen Noder:
Fra ovenstående skærmbillede kan vi fortælle, at hver backend-server på multi-writer-lytter får maksimalt 8 forbindelser. 4 samtidige sessioner kører. Disse er fremhævet i den øverste røde firkant, mens den enkeltskrivende lytter betjener henholdsvis 2 forbindelser og videresender dem til en enkelt node.
Konklusion
Konfiguration af de maksimale forbindelser til HAProxy- og MySQL-servere er vigtigt for at sikre god belastningsfordeling til vores databaseservere og beskytte MySQL-serverne mod at overbelaste eller udmatte dets forbindelser.