HAProxyとProxySQLはどちらもMySQLの世界で非常に人気のあるロードバランサーですが、これらのプロキシには大きな違いがあります。ここでは詳しく説明しません。HAProxyチュートリアルのHAProxyとProxySQLチュートリアルのProxySQLについて詳しく読むことができます。最も重要な違いは、ProxySQLがSQL対応プロキシであり、トラフィックを解析してMySQLプロトコルを理解するため、高度なトラフィックシェーピングに使用できることです。クエリをブロックし、書き換え、特定のホストに転送し、キャッシュすることができます。それらともっとたくさん。一方、HAProxyは、非常にシンプルでありながら効率的なレイヤー4プロキシであり、バックエンドにパケットを送信するだけです。 ProxySQLを使用して、読み取りと書き込みの分割を実行できます。SQLを理解し、クエリがSELECTであるかどうかを検出し、それに応じてルーティングするように構成できます。SELECTはすべてのノードに、他のクエリはマスターのみに。この機能は、マスターとスレーブに2つの別々のポートと2つの別々のバックエンドを使用する必要があるHAProxyでは使用できません。読み取りと書き込みの分割はアプリケーション側で実行する必要があります。
ProxySQLに移行する理由
上で説明した違いに基づいて、HAProxyからProxySQLに切り替える主な理由は、HAProxyに読み取りと書き込みの分割がないためであると言えます。 MySQLデータベースのクラスターを使用していて、それが非同期レプリケーションであるかGalera Clusterであるかは実際には問題ではない場合は、書き込みから読み取りを分割できるようにする必要があります。 MySQLレプリケーションの場合、書き込みは常にマスターに送信する必要があるため、これがデータベースクラスターを利用する唯一の方法であることは明らかです。したがって、読み取りと書き込みの分割を実行できない場合は、マスターにのみクエリを送信できます。ガレラにとって、読み取りと書き込みの分割は必須ではありませんが、間違いなく必要なものです。もちろん、HAProxyですべてのGaleraノードを1つのバックエンドとして構成し、ラウンドロビン方式ですべてのノードにトラフィックを送信できますが、これにより、複数のノードからの書き込みが互いに競合し、デッドロックとパフォーマンスの低下につながる可能性があります。また、Galeraクラスター内で問題やバグが発生しました。これらが修正されるまで、回避策はすべての書き込みを単一のノードに送信することでした。したがって、ベストプラクティスは、すべての書き込みを1つのGaleraノードに送信することです。これにより、動作がより安定し、パフォーマンスが向上します。
ProxySQLに移行するもう1つの非常に良い理由は、トラフィックをより適切に制御する必要があることです。 HAProxyでは、何もできません。トラフィックをバックエンドに送信するだけです。 ProxySQLを使用すると、クエリルールを使用してトラフィックを形成できます(正規表現、ユーザー、スキーマ、ソースホストなどを使用してトラフィックを照合します)。 OLAP SELECTを分析スレーブにリダイレクトできます(レプリケーションとGaleraの両方に当てはまります)。一部のSELECTをマスターからリダイレクトすることにより、マスターをオフロードできます。 SQLファイアウォールを実装できます。一部のクエリに遅延を追加できます。事前定義された時間より長くかかる場合は、クエリを強制終了できます。クエリを書き直して、オプティマイザのヒントを追加できます。これらすべてがHAProxyでは不可能です。
HAProxyからProxySQLに移行する方法
まず、次のトポロジについて考えてみましょう...
ClusterControlMySQLトポロジ ClusterControlのMySQLレプリケーションクラスターここに、マスターと2つのスレーブで構成されるレプリケーションクラスターがあります。 2つのHAProxyノードがデプロイされており、それぞれが2つのバックエンドを使用しています。マスター(書き込み)用のポート3307と、すべてのノード(読み取り)用の3308です。 Keepalivedは、これら2つのHAProxyインスタンスに仮想IPを提供するために使用されます。一方が失敗した場合は、もう一方が使用されます。このアプリケーションは、VIPを介してHAProxyインスタンスの1つに直接接続します。アプリケーション(Sysbenchを使用)が読み取り/書き込み分割を実行できないため、「ライター」バックエンドに接続する必要があると仮定します。その結果、負荷の大部分はマスター(10.0.0.101)にかかります。
ProxySQLに移行する手順は何ですか?ちょっと考えてみよう。まず、ProxySQLをデプロイして構成する必要があります。 ProxySQLにサーバーを追加し、必要な監視ユーザーを作成し、適切なクエリルールを作成する必要があります。最後に、ProxySQLの上にKeepalivedをデプロイし、別の仮想IPを作成してから、アプリケーションをHAProxyからProxySQLに可能な限りシームレスに切り替える必要があります。
それをどのように達成できるか見てみましょう...
ProxySQLのインストール方法
ProxySQLはさまざまな方法でインストールできます。 ProxySQL自体(https://repo.proxysql.com)からリポジトリを使用できます。または、Percona XtraDB Clusterを使用する場合は、CLIに依存しているため追加の構成が必要になる場合がありますが、PerconaリポジトリからProxySQLをインストールすることもできます。 PXC用に作成された管理ツール。レプリケーションについて話していることを考えると、レプリケーションを使用すると事態がさらに複雑になる可能性があります。最後に、ProxySQL GitHubからダウンロードした後、ProxySQLバイナリをインストールすることもできます。現在、1.4.xと2.0.xの2つの安定したバージョンがあります。 ProxySQL1.4とProxySQL2.0の間には機能の点で違いがあります。このブログでは、1.4.xブランチを使用します。これは、テストが適切であり、機能セットで十分であるためです。
ProxySQLリポジトリを使用し、ProxySQLを2つの追加ノード(10.0.0.103と10.0.0.104)にデプロイします。
まず、公式リポジトリを使用してProxySQLをインストールします。また、MySQLクライアントがインストールされていることを確認します(ProxySQLの構成に使用します)。私たちが行うプロセスは製品グレードではないことに注意してください。本番環境では、少なくとも管理ユーザーのデフォルトの資格情報を変更する必要があります。また、構成を確認して、期待と要件に沿っていることを確認する必要があります。
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
これで、ProxySQLが開始されたので、CLIを使用してProxySQLを構成します。
mysql -uadmin -padmin -P6032 -h127.0.0.1
まず、バックエンドサーバーとレプリケーションホストグループを定義します。
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)
サーバーは3つあり、ProxySQLはマスター(read_only =0のノード)にホストグループ10を使用し、スレーブ(read_only =1)にホストグループ20を使用する必要があることも定義しました。
次のステップとして、ProxySQLが監視できるように、MySQLノードに監視ユーザーを追加する必要があります。デフォルトを使用します。理想的には、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)
したがって、パスワード「monitor」を使用してユーザー「monitor」を作成する必要があります。これを行うには、マスターMySQLサーバーで次の許可を実行する必要があります。
mysql> create user [email protected]'%' identified by 'monitor';
Query OK, 0 rows affected (0.56 sec)
ProxySQLに戻る-アプリケーションがMySQLとクエリルールにアクセスするために使用するユーザーを構成する必要があります。これは、読み取りと書き込みの分割を提供することを目的としています。
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)
プレーンテキストでパスワードを使用し、それをハッシュするためにProxySQLに依存することに注意してください。セキュリティ上の理由から、ここでMySQLパスワードハッシュを明示的に渡す必要があります。
最後に、すべての変更を適用する必要があります。
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)
また、実行時からハッシュされたパスワードをロードする必要があります。プレーンテキストのパスワードは、実行時構成にロードされるときにハッシュされます。ディスクにハッシュされたままにするには、実行時からロードしてからディスクに保存する必要があります。
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)
ProxySQLに関してはこれです。次の手順を実行する前に、アプリケーションサーバーからプロキシに接続できるかどうかを確認する必要があります。
[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
私たちの場合、すべてが良さそうです。次に、Keepalivedをインストールします。
キープアライブインストール
インストールは非常に簡単です(少なくとも私たちが使用したUbuntu 16.04では):
apt install keepalived
次に、両方のサーバーの構成ファイルを作成する必要があります。
マスターキープアライブノード:
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
}
キープアライブノードのバックアップ:
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
これで、両方のノードでキープアライブを開始できます:
service keepalived start
ログに、ノードの1つがMASTER状態になり、VIPがそのノードで起動されたという情報が表示されるはずです。
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
ご覧のとおり、ノード10.0.0.103でVIP(10.0.0.112)が発生しました。これで、トラフィックを古い設定から新しい設定に移動することで結論を出すことができます。
トラフィックをProxySQLセットアップに切り替える
それを行う方法には多くの方法がありますが、それは主に特定の環境によって異なります。 DNSを使用してHAProxyVIPを指すドメインを維持している場合は、そこで変更を加えるだけで、徐々に、すべての接続が新しいVIPを指すようになります。特に接続の詳細がハードコーディングされている場合は、アプリケーションに変更を加えることもできます。変更をロールアウトすると、ノードは新しいセットアップへの接続を開始します。どのように行っても、グローバルスイッチを作成する前に新しいセットアップをテストすることをお勧めします。ステージング環境でテストしたことは確かですが、少数のアプリサーバーを選択して新しいプロキシにリダイレクトし、パフォーマンスの観点からどのように見えるかを監視することは悪い考えではありません。以下は、テストに役立つiptablesを利用した簡単な例です。
ProxySQLホストで、トラフィックをホスト10.0.0.11およびポート3307からホスト10.0.0.112およびポート6033にリダイレクトします。
iptables -t nat -A OUTPUT -p tcp -d 10.0.0.111 --dport 3307 -j DNAT --to-destination 10.0.0.112:6033
アプリケーションによっては、Webサーバーまたは他のサービスを再起動する必要がある場合があります(アプリがデータベースへの接続の一定のプールを作成する場合)、またはProxySQLに対して新しい接続が開かれるのを待つだけです。 ProxySQLがトラフィックを受信していることを確認できます:
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 |
+-----------+--------+--------+-----------+---------+---------+-----------------------------------------------------------------------------+
以上で、トラフィックをHAProxyからProxySQLセットアップに移動しました。いくつかの手順を実行しましたが、サービスをほとんど中断することなく確実に実行できます。
ClusterControlを使用してHAProxyからProxySQLに移行する方法
前のセクションでは、ProxySQLセットアップを手動でデプロイしてからそれに移行する方法について説明しました。このセクションでは、ClusterControlを使用して同じ目的を達成する方法について説明します。初期設定はまったく同じであるため、ProxySQLの展開を続行する必要があります。
ClusterControlを使用したProxySQLの展開
ClusterControlでのProxySQLの展開は、ほんの数回のクリックの問題です。
ClusterControlにProxySQLをデプロイするノードのIPまたはホスト名を選択し、CLI管理ユーザーとMySQL監視ユーザーの資格情報を渡す必要がありました。既存のMySQLを使用することにし、アプリケーションで使用する「sbtest」@「%」ユーザーのアクセス詳細を渡しました。ロードバランサーで使用するノードを選択しました。また、レプリケーションにすでに苦しんでいるため、最大レプリケーションラグ(しきい値を超えた場合、ProxySQLはそのスレーブにトラフィックを送信しません)をデフォルトの10秒から100に増やしました。遅れ。しばらくすると、ProxySQLノードがクラスターに追加されます。
ClusterControlを使用したProxySQL用のKeepalivedのデプロイ
ProxySQLノードが追加されたら、Keepalivedをデプロイします。
ClusterControlのProxySQLでキープアライブキープアライブをデプロイするProxySQLノード、仮想IP、およびVIPがバインドされるインターフェイスを選択するだけです。展開が完了すると、上記の「ProxySQLセットアップへのトラフィックの切り替え」セクションで説明した方法のいずれかを使用して、トラフィックを新しいセットアップに切り替えます。
ClusterControlでのProxySQLトラフィックの監視負荷グラフを確認することで、トラフィックがProxySQLに切り替わったことを確認できます。ご覧のとおり、負荷はクラスター内のノード全体にはるかに分散しています。下のグラフでも確認できます。これは、クラスター全体でのクエリの分布を示しています。
ClusterControlのProxySQLダッシュボード最後に、ProxySQLダッシュボードは、トラフィックがクラスター内のすべてのノードに分散されていることも示しています。
ClusterControlのProxySQLダッシュボードご覧のとおり、ClusterControlが新しいアーキテクチャをデプロイするのに少し時間がかかり、数回クリックするだけで実行できるので、このブログ投稿の恩恵を受けることを願っています。そのような移行の経験について教えてください。