HAProxy och ProxySQL är båda mycket populära lastbalanserare i MySQL-världen, men det finns en betydande skillnad mellan båda dessa proxyservrar. Vi går inte in på detaljer här, du kan läsa mer om HAProxy i HAProxy Tutorial och ProxySQL i ProxySQL Tutorial. Den viktigaste skillnaden är att ProxySQL är SQL-medveten proxy, den analyserar trafiken och förstår MySQL-protokollet och som sådan kan den användas för avancerad trafikformning - du kan blockera frågor, skriva om dem, dirigera dem till särskilda värdar, cache dem och många fler. HAProxy, å andra sidan, är en mycket enkel men effektiv lager 4-proxy och allt den gör är att skicka paket till backend. ProxySQL kan användas för att utföra en läs-skrivdelning - den förstår SQL och den kan konfigureras för att upptäcka om en fråga är SELECT eller inte och dirigera dem därefter:SELECTs till alla noder, andra frågor att bemästra. Den här funktionen är inte tillgänglig i HAProxy, som måste använda två separata portar och två separata backends för master och slavar – läs-skrivdelningen måste utföras på applikationssidan.
Varför migrera till ProxySQL?
Baserat på skillnaderna vi förklarade ovan skulle vi säga att huvudorsaken till att du kanske vill byta från HAProxy till ProxySQL är på grund av bristen på läs-skriv-delningen i HAProxy. Om du använder ett kluster av MySQL-databaser, och det spelar ingen roll om det är asynkron replikering eller Galera Cluster, vill du förmodligen kunna dela läsningar från skrivningar. För MySQL-replikering skulle detta uppenbarligen vara det enda sättet att använda ditt databaskluster eftersom skrivningar alltid måste skickas till mastern. Därför kan du bara skicka frågor till mastern om du inte kan göra läs-skrivdelningen. För Galera är läs-skrivdelning inte ett måste utan definitivt ett bra att ha. Visst, du kan konfigurera alla Galera-noder som en backend i HAProxy och skicka trafik till dem alla på ett round-robin-sätt, men detta kan resultera i att skrivningar från flera noder kommer i konflikt med varandra, vilket leder till dödlägen och prestandafall. Vi har också sett problem och buggar inom Galera-klustret, för vilka, tills de har åtgärdats, lösningen var att rikta alla skrivningar till en enda nod. Därför är den bästa praxisen att skicka alla skrivningar till en Galera-nod eftersom detta leder till stabilare beteende och bättre prestanda.
En annan mycket bra anledning till migrering till ProxySQL är ett behov av att ha bättre kontroll över trafiken. Med HAProxy kan du inte göra någonting - den skickar bara trafiken till sina backends. Med ProxySQL kan du forma din trafik med hjälp av frågeregler (matcha trafik med reguljära uttryck, användare, schema, källvärd och många fler). Du kan omdirigera OLAP SELECTs till analysslav (det är sant för både replikering och Galera). Du kan ladda ner din master genom att omdirigera några av SELECT:erna från den. Du kan implementera SQL-brandvägg. Du kan lägga till en fördröjning för några av frågorna, du kan döda frågor om de tar mer än en fördefinierad tid. Du kan skriva om frågor för att lägga till optimeringstips. Alla dessa är inte möjliga med HAProxy.
Hur migreras från HAProxy till ProxySQL?
Låt oss först betrakta följande topologi...
ClusterControl MySQL-topologi MySQL-replikeringskluster i ClusterControlVi har här ett replikeringskluster som består av en master och två slavar. Vi har två HAProxy-noder utplacerade, var och en använder två backends - på port 3307 för master (skriver) och 3308 för alla noder (läser). Keepalived används för att tillhandahålla en virtuell IP över dessa två HAProxy-instanser - skulle en av dem misslyckas kommer en annan att användas. Vår applikation ansluter direkt till VIP, genom den till en av HAProxy-instanserna. Låt oss anta att vår applikation (vi kommer att använda Sysbench) inte kan göra läs-skrivdelningen, därför måste vi ansluta till "writer"-backend. Som ett resultat är majoriteten av belastningen på vår master (10.0.0.101).
Vilka skulle vara stegen för att migrera till ProxySQL? Låt oss tänka på det ett ögonblick. Först måste vi distribuera och konfigurera ProxySQL. Vi måste lägga till servrar till ProxySQL, skapa nödvändiga övervakningsanvändare och skapa korrekta frågeregler. Slutligen måste vi distribuera Keepalived ovanpå ProxySQL, skapa en annan virtuell IP och sedan säkerställa en så sömlös switch som möjligt för vår applikation från HAProxy till ProxySQL.
Låt oss ta en titt på hur vi kan åstadkomma det...
Hur man installerar ProxySQL
Man kan installera ProxySQL på många sätt. Du kan använda repository, antingen från själva ProxySQL (https://repo.proxysql.com) eller om du råkar använda Percona XtraDB Cluster, kan du också installera ProxySQL från Percona repository även om det kan kräva ytterligare konfiguration eftersom det är beroende av CLI adminverktyg skapade för PXC. Med tanke på att vi pratar om replikering, kan användningen av dem bara göra saker mer komplexa. Slutligen kan du också installera ProxySQL-binärfiler efter att du laddat ner dem från ProxySQL GitHub. För närvarande finns det två stabila versioner, 1.4.x och 2.0.x. Det finns skillnader mellan ProxySQL 1.4 och ProxySQL 2.0 när det gäller funktioner, för den här bloggen kommer vi att hålla oss till 1.4.x-grenen, eftersom den är bättre testad och funktionsuppsättningen räcker för oss.
Vi kommer att använda ProxySQL-förrådet och vi kommer att distribuera ProxySQL på ytterligare två noder:10.0.0.103 och 10.0.0.104.
Först installerar vi ProxySQL med det officiella förvaret. Vi kommer också att se till att MySQL-klienten är installerad (vi kommer att använda den för att konfigurera ProxySQL). Tänk på att processen vi går igenom inte är produktionsklassad. För produktion vill du åtminstone ändra standardinloggningsuppgifterna för den administrativa användaren. Du kommer också att vilja granska konfigurationen och se till att den är i linje med dina förväntningar och krav.
apt-get install -y lsb-release
wget -O - 'https://repo.proxysql.com/ProxySQL/repo_pub_key' | apt-key add -
echo deb https://repo.proxysql.com/ProxySQL/proxysql-1.4.x/$(lsb_release -sc)/ ./ | tee /etc/apt/sources.list.d/proxysql.list
apt-get -y update
apt-get -y install proxysql
service proxysql start
Nu när ProxySQL har startats kommer vi att använda CLI för att konfigurera ProxySQL.
mysql -uadmin -padmin -P6032 -h127.0.0.1
Först kommer vi att definiera backend-servrar och replikeringsvärdgrupper:
mysql> INSERT INTO mysql_servers (hostgroup_id, hostname) VALUES (10, '10.0.0.101'), (20, '10.0.0.102'), (20, '10.0.0.103');
Query OK, 3 rows affected (0.91 sec)
mysql> INSERT INTO mysql_replication_hostgroups (writer_hostgroup, reader_hostgroup) VALUES (10, 20);
Query OK, 1 row affected (0.00 sec)
Vi har tre servrar, vi definierade också att ProxySQL ska använda värdgrupp 10 för master (nod med read_only=0) och värdgrupp 20 för slavar (read_only=1).
Som nästa steg måste vi lägga till en övervakningsanvändare på MySQL-noderna så att ProxySQL kan övervaka dem. Vi kommer att gå med standardinställningar, helst kommer du att ändra autentiseringsuppgifterna i ProxySQL.
mysql> SHOW VARIABLES LIKE 'mysql-monitor_username';
+------------------------+---------+
| Variable_name | Value |
+------------------------+---------+
| mysql-monitor_username | monitor |
+------------------------+---------+
1 row in set (0.00 sec)
mysql> SHOW VARIABLES LIKE 'mysql-monitor_password';
+------------------------+---------+
| Variable_name | Value |
+------------------------+---------+
| mysql-monitor_password | monitor |
+------------------------+---------+
1 row in set (0.00 sec)
Så vi måste skapa användarens "monitor" med lösenordet "monitor". För att göra det måste vi köra följande beviljande på master MySQL-servern:
mysql> create user [email protected]'%' identified by 'monitor';
Query OK, 0 rows affected (0.56 sec)
Tillbaka till ProxySQL - vi måste konfigurera användare som vår applikation kommer att använda för att komma åt MySQL och frågeregler, som är avsedda att ge oss en läs-skrivfördelning.
mysql> INSERT INTO mysql_users (username, password, default_hostgroup) VALUES ('sbtest', 'sbtest', 10);
Query OK, 1 row affected (0.34 sec)
mysql> INSERT INTO mysql_query_rules (rule_id,active,match_digest,destination_hostgroup,apply) VALUES (100, 1, '^SELECT.*FOR UPDATE$',10,1), (200,1,'^SELECT',20,1), (300,1,'.*',10,1);
Query OK, 3 rows affected (0.01 sec)
Observera att vi använde lösenord i vanlig text och vi kommer att lita på att ProxySQL hash det. För säkerhets skull bör du uttryckligen skicka in MySQL-lösenords-hash här.
Slutligen måste vi tillämpa alla ändringar.
mysql> LOAD MYSQL SERVERS TO RUNTIME;
Query OK, 0 rows affected (0.02 sec)
mysql> LOAD MYSQL USERS TO RUNTIME;
Query OK, 0 rows affected (0.01 sec)
mysql> LOAD MYSQL QUERY RULES TO RUNTIME;
Query OK, 0 rows affected (0.01 sec)
mysql> SAVE MYSQL SERVERS TO DISK;
Query OK, 0 rows affected (0.07 sec)
mysql> SAVE MYSQL QUERY RULES TO DISK;
Query OK, 0 rows affected (0.02 sec)
Vi vill också ladda de hashade lösenorden från runtime:vanlig textlösenord hashas när de laddas in i runtime-konfigurationen, för att hålla dem hashade på disken måste vi ladda dem från runtime och sedan lagra dem på disken:
mysql> SAVE MYSQL USERS FROM RUNTIME;
Query OK, 0 rows affected (0.00 sec)
mysql> SAVE MYSQL USERS TO DISK;
Query OK, 0 rows affected (0.02 sec)
Detta är det när det kommer till ProxySQL. Innan du gör ytterligare steg bör du kontrollera om du kan ansluta till proxyservrar från dina applikationsservrar.
[email protected]:~# mysql -h 10.0.0.103 -usbtest -psbtest -P6033 -e "SELECT * FROM sbtest.sbtest4 LIMIT 1\G"
mysql: [Warning] Using a password on the command line interface can be insecure.
*************************** 1. row ***************************
id: 1
k: 50147
c: 68487932199-96439406143-93774651418-41631865787-96406072701-20604855487-25459966574-28203206787-41238978918-19503783441
pad: 22195207048-70116052123-74140395089-76317954521-98694025897
I vårt fall ser allt bra ut. Nu är det dags att installera Keepalived.
Bevarad installation
Installationen är ganska enkel (åtminstone på Ubuntu 16.04, som vi använde):
apt install keepalived
Sedan måste du skapa konfigurationsfiler för båda servrarna:
Master keepalived nod:
vrrp_script chk_haproxy {
script "killall -0 haproxy" # verify the pid existance
interval 2 # check every 2 seconds
weight 2 # add 2 points of prio if OK
}
vrrp_instance VI_HAPROXY {
interface eth1 # interface to monitor
state MASTER
virtual_router_id 52 # Assign one ID for this route
priority 101
unicast_src_ip 10.0.0.103
unicast_peer {
10.0.0.104
}
virtual_ipaddress {
10.0.0.112 # the virtual IP
}
track_script {
chk_haproxy
}
# notify /usr/local/bin/notify_keepalived.sh
}
Backup keepalived nod:
vrrp_script chk_haproxy {
script "killall -0 haproxy" # verify the pid existance
interval 2 # check every 2 seconds
weight 2 # add 2 points of prio if OK
}
vrrp_instance VI_HAPROXY {
interface eth1 # interface to monitor
state MASTER
virtual_router_id 52 # Assign one ID for this route
priority 100
unicast_src_ip 10.0.0.103
unicast_peer {
10.0.0.104
}
virtual_ipaddress {
10.0.0.112 # the virtual IP
}
track_script {
chk_haproxy
}
# notify /usr/local/bin/notify_keepalived.sh
Det här är det, du kan börja keepalive på båda noderna:
service keepalived start
Du bör se information i loggarna om att en av noderna gick in i MASTER-tillstånd och att VIP har tagits upp på den noden.
May 7 09:52:11 vagrant systemd[1]: Starting Keepalive Daemon (LVS and VRRP)...
May 7 09:52:11 vagrant Keepalived[26686]: Starting Keepalived v1.2.24 (08/06,2018)
May 7 09:52:11 vagrant Keepalived[26686]: Opening file '/etc/keepalived/keepalived.conf'.
May 7 09:52:11 vagrant Keepalived[26696]: Starting Healthcheck child process, pid=26697
May 7 09:52:11 vagrant Keepalived[26696]: Starting VRRP child process, pid=26698
May 7 09:52:11 vagrant Keepalived_healthcheckers[26697]: Initializing ipvs
May 7 09:52:11 vagrant Keepalived_vrrp[26698]: Registering Kernel netlink reflector
May 7 09:52:11 vagrant Keepalived_vrrp[26698]: Registering Kernel netlink command channel
May 7 09:52:11 vagrant Keepalived_vrrp[26698]: Registering gratuitous ARP shared channel
May 7 09:52:11 vagrant systemd[1]: Started Keepalive Daemon (LVS and VRRP).
May 7 09:52:11 vagrant Keepalived_vrrp[26698]: Unable to load ipset library
May 7 09:52:11 vagrant Keepalived_vrrp[26698]: Unable to initialise ipsets
May 7 09:52:11 vagrant Keepalived_vrrp[26698]: Opening file '/etc/keepalived/keepalived.conf'.
May 7 09:52:11 vagrant Keepalived_vrrp[26698]: Using LinkWatch kernel netlink reflector...
May 7 09:52:11 vagrant Keepalived_healthcheckers[26697]: Registering Kernel netlink reflector
May 7 09:52:11 vagrant Keepalived_healthcheckers[26697]: Registering Kernel netlink command channel
May 7 09:52:11 vagrant Keepalived_healthcheckers[26697]: Opening file '/etc/keepalived/keepalived.conf'.
May 7 09:52:11 vagrant Keepalived_healthcheckers[26697]: Using LinkWatch kernel netlink reflector...
May 7 09:52:11 vagrant Keepalived_vrrp[26698]: pid 26701 exited with status 256
May 7 09:52:12 vagrant Keepalived_vrrp[26698]: VRRP_Instance(VI_HAPROXY) Transition to MASTER STATE
May 7 09:52:13 vagrant Keepalived_vrrp[26698]: pid 26763 exited with status 256
May 7 09:52:13 vagrant Keepalived_vrrp[26698]: VRRP_Instance(VI_HAPROXY) Entering MASTER STATE
May 7 09:52:15 vagrant Keepalived_vrrp[26698]: pid 26806 exited with status 256
[email protected]:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:ee:87:c4 brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:feee:87c4/64 scope link
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:fc:ac:21 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.103/24 brd 10.0.0.255 scope global eth1
valid_lft forever preferred_lft forever
inet 10.0.0.112/32 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fefc:ac21/64 scope link
valid_lft forever preferred_lft forever
Som du kan se, på nod 10.0.0.103 har en VIP (10.0.0.112) höjts. Vi kan nu avsluta med att flytta trafiken från den gamla inställningen till den nya.
Ändra trafik till en ProxySQL-installation
Det finns många metoder för hur man gör det, det beror mest på just din miljö. Om du råkar använda DNS för att upprätthålla en domän som pekar mot din HAProxy VIP, , kan du bara göra en ändring där och gradvis kommer alla anslutningar med tiden att peka om till den nya VIP. Du kan också göra en ändring i din applikation, särskilt om anslutningsdetaljerna är hårdkodade - när du väl rullar ut ändringen kommer noder att börja ansluta till den nya inställningen. Oavsett hur du gör det skulle det vara bra att testa den nya installationen innan du gör ett globalt byte. Du har säkert testat det i din iscensättningsmiljö, men det är ingen dålig idé att välja en handfull appservrar och omdirigera dem till den nya proxyn och övervaka hur de ser ut prestandamässigt. Nedan är ett enkelt exempel som använder iptables, vilket kan vara användbart för att testa.
På ProxySQL-värdarna omdirigerar du trafik från värd 10.0.0.11 och port 3307 till värd 10.0.0.112 och port 6033:
iptables -t nat -A OUTPUT -p tcp -d 10.0.0.111 --dport 3307 -j DNAT --to-destination 10.0.0.112:6033
Beroende på din applikation kan du behöva starta om webbservern eller andra tjänster (om din app skapar en konstant pool av anslutningar till databasen) eller bara vänta medan nya anslutningar kommer att öppnas mot ProxySQL. Du kan verifiera att ProxySQL tar emot trafiken:
mysql> show processlist;
+-----------+--------+--------+-----------+---------+---------+-----------------------------------------------------------------------------+
| SessionID | user | db | hostgroup | command | time_ms | info |
+-----------+--------+--------+-----------+---------+---------+-----------------------------------------------------------------------------+
| 12 | sbtest | sbtest | 20 | Sleep | 0 | |
| 13 | sbtest | sbtest | 10 | Query | 0 | DELETE FROM sbtest23 WHERE id=49957 |
| 14 | sbtest | sbtest | 10 | Query | 59 | DELETE FROM sbtest11 WHERE id=50185 |
| 15 | sbtest | sbtest | 20 | Query | 59 | SELECT c FROM sbtest8 WHERE id=46054 |
| 16 | sbtest | sbtest | 20 | Query | 0 | SELECT DISTINCT c FROM sbtest27 WHERE id BETWEEN 50115 AND 50214 ORDER BY c |
| 17 | sbtest | sbtest | 10 | Query | 0 | DELETE FROM sbtest32 WHERE id=50084 |
| 18 | sbtest | sbtest | 10 | Query | 26 | DELETE FROM sbtest28 WHERE id=34611 |
| 19 | sbtest | sbtest | 10 | Query | 16 | DELETE FROM sbtest4 WHERE id=50151 |
+-----------+--------+--------+-----------+---------+---------+-----------------------------------------------------------------------------+
Det var det, vi har flyttat trafiken från HAProxy till ProxySQL-installationen. Det tog några steg men det är definitivt genomförbart med mycket små avbrott i tjänsten.
Hur migreras från HAProxy till ProxySQL med ClusterControl?
I föregående avsnitt förklarade vi hur man manuellt distribuerar ProxySQL-installationen och sedan migrerar till den. I det här avsnittet skulle vi vilja förklara hur man uppnår samma mål med ClusterControl. Den initiala installationen är exakt densamma, därför måste vi fortsätta med distributionen av ProxySQL.
Distribuera ProxySQL med ClusterControl
Implementering av ProxySQL i ClusterControl är bara en fråga om en handfull klick.
Distribuera ProxySQL i ClusterControlVi var tvungna att välja en nods IP eller värdnamn, skicka inloggningsuppgifter för CLI-administrativ användare och MySQL-övervakningsanvändare. Vi bestämde oss för att använda befintliga MySQL och vi skickade åtkomstinformation för 'sbtest'@'%' användare som vi använder i applikationen. Vi valde vilka noder vi vill använda i lastbalanseraren, vi ökade också max replikeringsfördröjning (om den tröskeln passeras kommer ProxySQL inte att skicka trafiken till den slaven) från standard 10 sekunder till 100 eftersom vi redan lider av replikeringen eftersläpning. Efter en kort stund kommer ProxySQL-noder att läggas till i klustret.
Distribuera Keepalived för ProxySQL med ClusterControl
När ProxySQL-noder har lagts till är det dags att distribuera Keepalived.
Bevaras med ProxySQL i ClusterControlAllt vi behövde göra är att välja vilka ProxySQL-noder vi vill att Keepalved ska distribuera på, virtuell IP och gränssnitt som VIP kommer att vara bunden till. När distributionen kommer att slutföras kommer vi att byta trafiken till den nya installationen med en av metoderna som nämns i avsnittet "Byt trafik till ProxySQL-installation" ovan.
Övervaka ProxySQL-trafik i ClusterControlVi kan verifiera att trafiken har gått över till ProxySQL genom att titta på belastningsgrafen – som du kan se är belastningen mycket mer fördelad över noderna i klustret. Du kan också se det i diagrammet nedan, som visar sökfrågornas fördelning över klustret.
ProxySQL Dashboard i ClusterControlSlutligen visar ProxySQL-instrumentpanelen också att trafiken är fördelad över alla noder i klustret:
ProxySQL Dashboard i ClusterControlVi hoppas att du kommer att dra nytta av det här blogginlägget, som du kan se, med ClusterControls implementering av den nya arkitekturen tar bara ett ögonblick och kräver bara en handfull klick för att få saker att fungera. Berätta för oss om din erfarenhet av sådana migrationer.