ProxySQL je inteligentní a vysoce výkonný SQL proxy, který podporuje MySQL, MariaDB a ClickHouse. Nedávno se ProxySQL 2.0 stal GA a přichází s novými vzrušujícími funkcemi, jako je konzistentní čtení GTID, frontend SSL, nativní podpora Galera a MySQL Group Replication.
Je relativně snadné spustit ProxySQL jako kontejner Docker. Již dříve jsme psali o tom, jak spustit ProxySQL na Kubernetes jako pomocný kontejner nebo jako službu Kubernetes, která je založena na ProxySQL 1.x. V tomto příspěvku na blogu budeme používat novou verzi ProxySQL 2.x, která používá jiný přístup ke konfiguraci Galera Cluster.
ProxySQL 2.x Docker Image
Vydali jsme nový kontejner obrázků ProxySQL 2.0 Docker a je k dispozici v Docker Hub. Soubor README poskytuje řadu příkladů konfigurace zejména pro Galera a MySQL Replication, pre a po v2.x. Konfigurační řádky mohou být definovány v textovém souboru a namapovány do cesty kontejneru v /etc/proxysql.cnf, aby byly načteny do služby ProxySQL.
Značka image "nejnovější" stále ukazuje na 1.x, dokud se ProxySQL 2.0 oficiálně nestane GA (zatím jsme neviděli žádný oficiální blog/článek o vydání od týmu ProxySQL). Což znamená, že kdykoli nainstalujete obraz ProxySQL pomocí nejnovější značky od společnosti Somenines, stále s ním získáte verzi 1.x. Všimněte si, že nové ukázkové konfigurace také umožňují webové statistiky ProxySQL (zavedené ve verzi 1.4.4, ale stále ve verzi beta) – jednoduchý řídicí panel, který shrnuje celkovou konfiguraci a stav samotného ProxySQL.
Podpora proxySQL 2.x pro Galera Cluster
Promluvme si o nativní podpoře Galera Cluster podrobněji. Nová tabulka mysql_galera_hostgroups se skládá z následujících polí:
- writer_hostgroup : ID hostitelské skupiny, která bude obsahovat všechny členy, kteří jsou autory (read_only=0).
- backup_writer_hostgroup : Pokud cluster běží v režimu více zapisovačů (tj. existuje více uzlů s read_only=0) a max_writers je nastaveno na menší počet, než je celkový počet uzlů, další uzly se přesunou do této hostitelské skupiny záložního zapisovače.
- reader_hostgroup : ID hostitelské skupiny, která bude obsahovat všechny členy, kteří jsou čtenáři (tj. uzly, které mají read_only=1)
- offline_hostgroup : Když monitorování ProxySQL určí hostitele jako OFFLINE, bude hostitel přesunut do offline_hostgroup.
- aktivní : booleovská hodnota (0 nebo 1) pro aktivaci hostitelské skupiny
- max_writers : Řídí maximální počet povolených uzlů v hostitelské skupině zapisovače, jak již bylo zmíněno dříve, další uzly budou přesunuty do skupiny hostitelů backup_writer_hostgroup.
- writer_is_also_reader : Když je 1, uzel ve skupině hostitelů spisovatele bude také umístěn do skupiny hostitelů čtenářů, takže bude použit pro čtení. Je-li nastaveno na 2, uzly ze skupiny backup_writer_hostgroup budou umístěny do read_hostgroup namísto uzlů ve skupině Writer_hostgroup.
- max_transactions_behind : určuje maximální počet sad zápisů, které může mít uzel v clusteru zařazený do fronty, než bude uzel ZABLOKOVÁN, aby se zabránilo zastaralému čtení (toto se určuje dotazem na proměnnou wsrep_local_recv_queue Galera).
- komentář : Textové pole, které lze použít pro jakékoli účely definované uživatelem
Zde je příklad konfigurace pro mysql_galera_hostgroups ve formátu tabulky:
Admin> select * from mysql_galera_hostgroups\G
*************************** 1. row ***************************
writer_hostgroup: 10
backup_writer_hostgroup: 20
reader_hostgroup: 30
offline_hostgroup: 9999
active: 1
max_writers: 1
writer_is_also_reader: 2
max_transactions_behind: 20
comment:
ProxySQL provádí kontroly stavu Galera sledováním následujícího stavu/proměnné MySQL:
- pouze pro čtení - Pokud je ZAPNUTO, pak ProxySQL seskupí definovaného hostitele do reader_hostgroup, pokud Write_is_also_reader není 1.
- wsrep_desync - Pokud je ZAPNUTO, ProxySQL označí uzel jako nedostupný a přesune jej do offline_hostgroup.
- wsrep_reject_queries - Pokud je tato proměnná zapnutá, ProxySQL označí uzel jako nedostupný a přesune jej do offline_hostgroup (užitečné v určitých situacích údržby).
- wsrep_sst_donor_rejects_queries - Pokud je tato proměnná zapnutá, ProxySQL označí uzel jako nedostupný, zatímco uzel Galera slouží jako dárce SST, a přesune jej do offline_hostgroup.
- wsrep_local_state - Pokud se tento stav vrátí na jiný než 4 (4 znamená Synchronizováno), ProxySQL označí uzel jako nedostupný a přesune jej do offline_hostgroup.
- wsrep_local_recv_queue – Pokud je tento stav vyšší než max_transactions_behind, uzel bude vyřazen.
- wsrep_cluster_status - Pokud se vrátí tento stav jiný než Primární, ProxySQL označí uzel jako nedostupný a přesune jej do offline_hostgroup.
Jak již bylo řečeno, zkombinováním těchto nových parametrů v mysql_galera_hostgroups spolu s mysql_query_rules má ProxySQL 2.x flexibilitu, aby se vešlo do mnohem více případů použití Galery. Například lze mít hostitelské skupiny s jedním zapisovacím zařízením, s více zapisovacími zařízeními a s více čtecími zařízeními definované jako cílová hostitelská skupina pravidla dotazu, se schopností omezit počet zapisovatelů a jemnější kontrolou chování zastaralého čtení.
Porovnejte to s ProxySQL 1.x, kde uživatel musel explicitně definovat plánovač pro volání externího skriptu pro provedení kontroly stavu backendu a aktualizaci stavu databázových serverů. To vyžaduje určité přizpůsobení skriptu (uživatel musí aktualizovat uživatele/heslo/port ProxySQL admin) a navíc to záviselo na dalším nástroji (klient MySQL) pro připojení k rozhraní správce ProxySQL.
Zde je příklad konfigurace plánovače skriptu kontroly stavu Galera ve formátu tabulky pro ProxySQL 1.x:
Admin> select * from scheduler\G
*************************** 1. row ***************************
id: 1
active: 1
interval_ms: 2000
filename: /usr/share/proxysql/tools/proxysql_galera_checker.sh
arg1: 10
arg2: 20
arg3: 1
arg4: 1
arg5: /var/lib/proxysql/proxysql_galera_checker.log
comment:
Kromě toho, protože vlákno plánovače ProxySQL provádí jakýkoli skript nezávisle, existuje mnoho verzí skriptů pro kontrolu stavu. Všechny instance ProxySQL nasazené pomocí ClusterControl používají výchozí skript poskytovaný instalačním balíčkem ProxySQL.
V ProxySQL 2.x mohou proměnné max_writers a Writer_is_also_reader určovat, jak ProxySQL dynamicky seskupuje backendové servery MySQL a bude přímo ovlivňovat distribuci připojení a směrování dotazů. Vezměme si například následující backendové servery MySQL:
Admin> select hostgroup_id, hostname, status, weight from mysql_servers;
+--------------+--------------+--------+--------+
| hostgroup_id | hostname | status | weight |
+--------------+--------------+--------+--------+
| 10 | DB1 | ONLINE | 1 |
| 10 | DB2 | ONLINE | 1 |
| 10 | DB3 | ONLINE | 1 |
+--------------+--------------+--------+--------+
Společně s následující definicí hostitelských skupin Galera:
Admin> select * from mysql_galera_hostgroups\G
*************************** 1. row ***************************
writer_hostgroup: 10
backup_writer_hostgroup: 20
reader_hostgroup: 30
offline_hostgroup: 9999
active: 1
max_writers: 1
writer_is_also_reader: 2
max_transactions_behind: 20
comment:
Vzhledem k tomu, že jsou všichni hostitelé v provozu, ProxySQL s největší pravděpodobností seskupí hostitele následovně:
Pojďme se na ně podívat jeden po druhém:
Konfigurace | Popis |
---|---|
writer_is_also_reader=0 |
|
writer_is_also_reader=1 |
|
writer_is_also_reader=2 |
|
S touto konfigurací můžete mít různé volby pro cíl hostitelské skupiny, aby bylo možné uspokojit konkrétní pracovní zátěže. Zápisy "hotspot" lze nakonfigurovat tak, aby šly pouze na jeden server, aby se omezily konflikty mezi více mastery, nekonfliktní zápisy mohou být distribuovány rovnoměrně na ostatních masterech, většina čtení může být distribuována rovnoměrně na všech serverech MySQL nebo bez zápisu, kritická čtení lze přeposílat na nejaktuálnější servery a analytická čtení lze předávat do podřízené repliky.
Nasazení proxySQL pro Galera Cluster
V tomto příkladu předpokládejme, že již máme tříuzlový cluster Galera nasazený ClusterControl, jak je znázorněno na následujícím diagramu:
Naše aplikace Wordpress běží na Dockeru, zatímco databáze Wordpress je hostována na našem Galera Cluster běžícím na holých serverech. Rozhodli jsme se spustit kontejner ProxySQL vedle našich kontejnerů Wordpress, abychom měli lepší kontrolu nad směrováním databázových dotazů Wordpress a plně využili naši infrastrukturu databázového clusteru. Protože poměr čtení a zápisu je kolem 80%-20%, chceme nakonfigurovat ProxySQL na:
- Přesměrovat všechny zápisy do jednoho uzlu Galera (méně konfliktů, zaměřit se na zápis)
- Vyvážit všechna čtení do dalších dvou uzlů Galera (lepší distribuce pro většinu zátěže)
Nejprve vytvořte konfigurační soubor ProxySQL uvnitř hostitele Docker, abychom jej mohli namapovat do našeho kontejneru:
$ mkdir /root/proxysql-docker
$ vim /root/proxysql-docker/proxysql.cnf
Poté zkopírujte následující řádky (konfigurační řádky vysvětlíme níže):
datadir="/var/lib/proxysql"
admin_variables=
{
admin_credentials="admin:admin"
mysql_ifaces="0.0.0.0:6032"
refresh_interval=2000
web_enabled=true
web_port=6080
stats_credentials="stats:admin"
}
mysql_variables=
{
threads=4
max_connections=2048
default_query_delay=0
default_query_timeout=36000000
have_compress=true
poll_timeout=2000
interfaces="0.0.0.0:6033;/tmp/proxysql.sock"
default_schema="information_schema"
stacksize=1048576
server_version="5.1.30"
connect_timeout_server=10000
monitor_history=60000
monitor_connect_interval=200000
monitor_ping_interval=200000
ping_interval_server_msec=10000
ping_timeout_server=200
commands_stats=true
sessions_sort=true
monitor_username="proxysql"
monitor_password="proxysqlpassword"
monitor_galera_healthcheck_interval=2000
monitor_galera_healthcheck_timeout=800
}
mysql_galera_hostgroups =
(
{
writer_hostgroup=10
backup_writer_hostgroup=20
reader_hostgroup=30
offline_hostgroup=9999
max_writers=1
writer_is_also_reader=1
max_transactions_behind=30
active=1
}
)
mysql_servers =
(
{ address="db1.cluster.local" , port=3306 , hostgroup=10, max_connections=100 },
{ address="db2.cluster.local" , port=3306 , hostgroup=10, max_connections=100 },
{ address="db3.cluster.local" , port=3306 , hostgroup=10, max_connections=100 }
)
mysql_query_rules =
(
{
rule_id=100
active=1
match_pattern="^SELECT .* FOR UPDATE"
destination_hostgroup=10
apply=1
},
{
rule_id=200
active=1
match_pattern="^SELECT .*"
destination_hostgroup=30
apply=1
},
{
rule_id=300
active=1
match_pattern=".*"
destination_hostgroup=10
apply=1
}
)
mysql_users =
(
{ username = "wordpress", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 },
{ username = "sbtest", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 }
)
Nyní se pojďme podívat na některé z nejvíce konfiguračních sekcí. Nejprve definujeme konfiguraci hostitelských skupin Galera, jak je uvedeno níže:
mysql_galera_hostgroups =
(
{
writer_hostgroup=10
backup_writer_hostgroup=20
reader_hostgroup=30
offline_hostgroup=9999
max_writers=1
writer_is_also_reader=1
max_transactions_behind=30
active=1
}
)
Hostgroup 10 bude write_hostgroup, hostitelská skupina 20 pro backup_writer a hostitelská skupina 30 pro čtenáře. Nastavili jsme max_writers na 1, abychom mohli mít hostitelskou skupinu s jedním zapisovačem pro hostitelskou skupinu 10, kam by měly být odesílány všechny zápisy. Poté definujeme write_is_also_reader na 1, což učiní všechny uzly Galera jako čtenáře, vhodné pro dotazy, které mohou být rovnoměrně distribuovány do všech uzlů. Hostgroup 9999 je vyhrazena pro offline_hostgroup, pokud ProxySQL detekuje nefunkční uzly Galera.
Poté nakonfigurujeme naše servery MySQL s výchozím nastavením na hostitelskou skupinu 10:
mysql_servers =
(
{ address="db1.cluster.local" , port=3306 , hostgroup=10, max_connections=100 },
{ address="db2.cluster.local" , port=3306 , hostgroup=10, max_connections=100 },
{ address="db3.cluster.local" , port=3306 , hostgroup=10, max_connections=100 }
)
S výše uvedenými konfiguracemi bude ProxySQL „vidět“ naše hostitelské skupiny, jak je uvedeno níže:
Poté definujeme směrování dotazu pomocí pravidel dotazu. Na základě našeho požadavku by měla být všechna čtení odeslána do všech uzlů Galera kromě zapisovače (hostgroup 20) a vše ostatní je předáno hostitelské skupině 10 pro jednoho zapisovače:
mysql_query_rules =
(
{
rule_id=100
active=1
match_pattern="^SELECT .* FOR UPDATE"
destination_hostgroup=10
apply=1
},
{
rule_id=200
active=1
match_pattern="^SELECT .*"
destination_hostgroup=20
apply=1
},
{
rule_id=300
active=1
match_pattern=".*"
destination_hostgroup=10
apply=1
}
)
Nakonec definujeme uživatele MySQL, kteří budou předáváni přes ProxySQL:
mysql_users =
(
{ username = "wordpress", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 },
{ username = "sbtest", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 }
)
Transaction_persistent jsme nastavili na 0, takže všechna připojení od těchto uživatelů budou respektovat pravidla dotazů pro směrování čtení a zápisu. V opačném případě by spojení skončila tak, že by narazila na jednu hostitelskou skupinu, což maří účel vyrovnávání zátěže. Nezapomeňte tyto uživatele nejprve vytvořit na všech serverech MySQL. Pro uživatele ClusterControl můžete k vytvoření těchto uživatelů použít funkci Správa -> Schémata a uživatelé.
Nyní jsme připraveni spustit náš kontejner. Při spouštění kontejneru ProxySQL namapujeme konfigurační soubor ProxySQL jako připojení k připojení. Příkaz run tedy bude:
$ docker run -d \
--name proxysql2 \
--hostname proxysql2 \
--publish 6033:6033 \
--publish 6032:6032 \
--publish 6080:6080 \
--restart=unless-stopped \
-v /root/proxysql/proxysql.cnf:/etc/proxysql.cnf \
severalnines/proxysql:2.0
Nakonec změňte databázi Wordpress směřující na port kontejneru ProxySQL 6033, například:
$ docker run -d \
--name wordpress \
--publish 80:80 \
--restart=unless-stopped \
-e WORDPRESS_DB_HOST=proxysql2:6033 \
-e WORDPRESS_DB_USER=wordpress \
-e WORDPRESS_DB_HOST=passw0rd \
wordpress
V tuto chvíli naše architektura vypadá asi takto:
Pokud chcete, aby byl kontejner ProxySQL trvalý, namapujte /var/lib/proxysql/ na svazek Docker nebo připojte připojení, například:
$ docker run -d \
--name proxysql2 \
--hostname proxysql2 \
--publish 6033:6033 \
--publish 6032:6032 \
--publish 6080:6080 \
--restart=unless-stopped \
-v /root/proxysql/proxysql.cnf:/etc/proxysql.cnf \
-v proxysql-volume:/var/lib/proxysql \
severalnines/proxysql:2.0
Mějte na paměti, že při spuštění s trvalým úložištěm, jako je výše uvedené, bude náš /root/proxysql/proxysql.cnf při druhém restartu zastaralý. To je způsobeno vícevrstvou konfigurací ProxySQL, kdy pokud existuje /var/lib/proxysql/proxysql.db, ProxySQL přeskočí možnosti načítání z konfiguračního souboru a místo toho načte vše, co je v databázi SQLite (pokud nespustíte službu proxysql s --initial vlajka). Nicméně, další správa konfigurace ProxySQL musí být provedena prostřednictvím administrátorské konzole ProxySQL na portu 6032 namísto použití konfiguračního souboru.
Monitorování
Protokol procesů ProxySQL se ve výchozím nastavení protokoluje do syslog a můžete je zobrazit pomocí standardního příkazu docker:
$ docker ps
$ docker logs proxysql2
Chcete-li ověřit aktuální hostitelskou skupinu, dotazujte se na tabulku runtime_mysql_servers:
$ docker exec -it proxysql2 mysql -uadmin -padmin -h127.0.0.1 -P6032 --prompt='Admin> '
Admin> select hostgroup_id,hostname,status from runtime_mysql_servers;
+--------------+--------------+--------+
| hostgroup_id | hostname | status |
+--------------+--------------+--------+
| 10 | 192.168.0.21 | ONLINE |
| 30 | 192.168.0.21 | ONLINE |
| 30 | 192.168.0.22 | ONLINE |
| 30 | 192.168.0.23 | ONLINE |
| 20 | 192.168.0.22 | ONLINE |
| 20 | 192.168.0.23 | ONLINE |
+--------------+--------------+--------+
Pokud dojde k výpadku vybraného zapisovače, bude přenesen do offline_hostgroup (HID 9999):
Admin> select hostgroup_id,hostname,status from runtime_mysql_servers;
+--------------+--------------+--------+
| hostgroup_id | hostname | status |
+--------------+--------------+--------+
| 10 | 192.168.0.22 | ONLINE |
| 9999 | 192.168.0.21 | ONLINE |
| 30 | 192.168.0.22 | ONLINE |
| 30 | 192.168.0.23 | ONLINE |
| 20 | 192.168.0.23 | ONLINE |
+--------------+--------------+--------+
Výše uvedené změny topologie lze ilustrovat na následujícím diagramu:
Povolili jsme také uživatelské rozhraní webových statistik pomocí admin-web_enabled=true. Chcete-li získat přístup k webovému uživatelskému rozhraní, jednoduše přejděte na hostitele Docker na portu 6080, například:http://192.168.0.200:8060 a budete vyzváni s vyskakovacím oknem s uživatelským jménem/heslem. Zadejte přihlašovací údaje definované v admin-stats_credentials a měla by se vám zobrazit následující stránka:
Monitorováním tabulky poolů připojení MySQL můžeme získat přehled distribuce připojení pro všechny hostitelské skupiny:
Admin> select hostgroup, srv_host, status, ConnUsed, MaxConnUsed, Queries from stats.stats_mysql_connection_pool order by srv_host;
+-----------+--------------+--------+----------+-------------+---------+
| hostgroup | srv_host | status | ConnUsed | MaxConnUsed | Queries |
+-----------+--------------+--------+----------+-------------+---------+
| 20 | 192.168.0.23 | ONLINE | 5 | 24 | 11458 |
| 30 | 192.168.0.23 | ONLINE | 0 | 0 | 0 |
| 20 | 192.168.0.22 | ONLINE | 2 | 24 | 11485 |
| 30 | 192.168.0.22 | ONLINE | 0 | 0 | 0 |
| 10 | 192.168.0.21 | ONLINE | 32 | 32 | 9746 |
| 30 | 192.168.0.21 | ONLINE | 0 | 0 | 0 |
+-----------+--------------+--------+----------+-------------+---------+
Výše uvedený výstup ukazuje, že hostitelská skupina 30 nic nezpracovává, protože naše pravidla dotazů nemají tuto hostitelskou skupinu nakonfigurovanou jako cílovou hostitelskou skupinu.
Statistiky související s uzly Galera lze zobrazit v tabulce mysql_server_galera_log:
Admin> select * from mysql_server_galera_log order by time_start_us desc limit 3\G
*************************** 1. row ***************************
hostname: 192.168.0.23
port: 3306
time_start_us: 1552992553332489
success_time_us: 2045
primary_partition: YES
read_only: NO
wsrep_local_recv_queue: 0
wsrep_local_state: 4
wsrep_desync: NO
wsrep_reject_queries: NO
wsrep_sst_donor_rejects_queries: NO
error: NULL
*************************** 2. row ***************************
hostname: 192.168.0.22
port: 3306
time_start_us: 1552992553329653
success_time_us: 2799
primary_partition: YES
read_only: NO
wsrep_local_recv_queue: 0
wsrep_local_state: 4
wsrep_desync: NO
wsrep_reject_queries: NO
wsrep_sst_donor_rejects_queries: NO
error: NULL
*************************** 3. row ***************************
hostname: 192.168.0.21
port: 3306
time_start_us: 1552992553329013
success_time_us: 2715
primary_partition: YES
read_only: NO
wsrep_local_recv_queue: 0
wsrep_local_state: 4
wsrep_desync: NO
wsrep_reject_queries: NO
wsrep_sst_donor_rejects_queries: NO
error: NULL
Sada výsledků vrací související stav proměnné/stavu MySQL pro každý uzel Galera pro konkrétní časové razítko. V této konfiguraci jsme nakonfigurovali kontrolu stavu Galery tak, aby se spouštěla každé 2 sekundy (monitor_galera_healthcheck_interval=2000). Maximální doba převzetí služeb při selhání by tedy byla přibližně 2 sekundy, pokud by v clusteru došlo ke změně topologie.
Odkazy
- Podpora ProxySQL Native Galera
- Řešení HA a clustering:ProxySQL jako inteligentní směrovač pro Galera a Group Replication
- Obrázek ProxySQL Docker od společnosti Somenines
- Jak monitorovat ProxySQL pomocí Prometheus a ClusterControl