yum install perl-DBD-mysql gnutls
wget https://s3.cn-north-1.amazonaws.com.cn/myworkshop-lxy/proxysql/proxysql2-2.0.12-1.1.el7.x86_64.rpm
rpm -ivh proxysql2-2.0.12-1.1.el7.x86_64.rpm
service proxysql start
安装完成。
2、测试管理端口连接
执行如下命令:
mysql -u admin -padmin -h 127.0.0.1 -P6032 --prompt='Admin> '
如果可以返回以下信息,表示安装完成。
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 5.5.30 (ProxySQL Admin Module)
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
Admin>
以上看到的版本5.5.30并不是后台真实的MySQL实例的版本,这只是ProxySQL本身模拟的版本,因此是正常的。数据库解析SQL主要是看后端的MySQL版本是5.6、5.7还是8.0,与ProxySQL的显示的没有直接关系。
3、查询当前配置
查询当前server、查询转发规则、查询当前用户:
SELECT * FROM mysql_servers;
SELECT * from mysql_query_rules;
SELECT * FROM mysql_users;
以上查询结果应该均为空,表示是一个全新装好的服务器。
二、配置ProxySQL
1、设置默认管理员账号和对外服务端口
ProxySQL默认有两个端口,管理端口在6032,服务端口在6033。
ProxySQL的管理员账户在6032端口,默认是用户名是admin,密码也是admin。系统设计上,不允许管理员用户与MySQL普通用户重名。这就带来了一个使用场景的问题,即应用程序和后端MySQL经常使用admin作为用户名,这样将导致冲突无法登录。由此,我们在这里另外创建一个后续要使用的管理员账号叫做proxyadmin。然后我们将对外服务端口从6033改为程序代码常用的3306。本步骤非常重要,配置错误将导致无法登录ProxySQL的管理端口。
执行如下命令以默认账号admin/admin连接到ProxySQL的6032管理端口。
mysql -u admin -padmin -h 127.0.0.1 -P6032 --prompt='Admin> '
执行如下命令:
SET admin-admin_credentials='proxyadmin:proxyadmin';
load admin variables to runtime;
save admin variables to disk;
SET mysql-interfaces='0.0.0.0:3306';
SAVE MYSQL VARIABLES TO DISK;
PROXYSQL RESTART;
执行完毕后,服务会中断,输入quit,退出到Linux Console,然后重新连接到6032的管理端口。重新连接时候,就可以使用新的proxyadmin用户名和密码登录了。命令如下:
mysql -u proxyadmin -pproxyadmin -h 127.0.0.1 -P6032 --prompt='Admin>
登录成功就表示配置成功。此时服务端口3306还不能登录,有待后续配置。
2、新增后端节点
假设ProxySQL的后台是AWS Aurora for MySQL数据库,有一个Writer节点(主节点)和一个Reader节点(只读节点),那么执行如下命令,新增两个节点,且分别配置两个节点的组ID为1和2。其中hostgroup_id=1是可写入的主节点。
INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES (1,'proxy-test-cluster.cluster-cfvonviibzua.rds.cn-north-1.amazonaws.com.cn',3306);
INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES (2,'proxy-test-cluster.cluster-ro-cfvonviibzua.rds.cn-north-1.amazonaws.com.cn',3306);
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
配置成功后可运行如下命令检查配置正确:
SELECT * FROM mysql_servers;
正常的话应返回类似如下的信息:
Admin> SELECT * FROM mysql_servers;
+--------------+----------------------------------------------------------------------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| hostgroup_id | hostname | port | gtid_port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment |
+--------------+----------------------------------------------------------------------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| 1 | proxy-test-cluster.cluster-cfvonviibzua.rds.cn-north-1.amazonaws.com.cn | 3306 | 0 | ONLINE | 1 | 0 | 1000 | 0 | 0 | 0 | |
| 2 | proxy-test-cluster.cluster-ro-cfvonviibzua.rds.cn-north-1.amazonaws.com.cn | 3306 | 0 | ONLINE | 1 | 0 | 1000 | 0 | 0 | 0 | |
+--------------+----------------------------------------------------------------------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
2 rows in set (0.00 sec)
Admin>
3、新增流量规则
首先定义默认节点,如果规则没有显式声明,则所有流量送往主节点。接下来定义规则,将所有查询语句送往只读节点,其中Select for update特殊对待还送往主节点。执行如下命令:
UPDATE mysql_users SET default_hostgroup=1;
INSERT INTO mysql_query_rules (rule_id,active,match_digest,destination_hostgroup,apply)
VALUES
(1,1,'^SELECT.*FOR UPDATE$',1,1),
(2,1,'^SELECT',2,1);
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
配置成功后可运行如下命令检查配置正确:
SELECT * from mysql_query_rules;
正常的话应返回类似如下的信息:
Admin> SELECT * from mysql_query_rules;
+---------+--------+----------+------------+--------+-------------+------------+------------+--------+----------------------+---------------+----------------------+--------------+---------+-----------------+-----------------------+-----------+--------------------+---------------+-----------+---------+---------+-------+-------------------+----------------+------------------+-----------+--------+-------------+-----------+---------------------+-----+-------+---------+
| rule_id | active | username | schemaname | flagIN | client_addr | proxy_addr | proxy_port | digest | match_digest | match_pattern | negate_match_pattern | re_modifiers | flagOUT | replace_pattern | destination_hostgroup | cache_ttl | cache_empty_result | cache_timeout | reconnect | timeout | retries | delay | next_query_flagIN | mirror_flagOUT | mirror_hostgroup | error_msg | OK_msg | sticky_conn | multiplex | gtid_from_hostgroup | log | apply | comment |
+---------+--------+----------+------------+--------+-------------+------------+------------+--------+----------------------+---------------+----------------------+--------------+---------+-----------------+-----------------------+-----------+--------------------+---------------+-----------+---------+---------+-------+-------------------+----------------+------------------+-----------+--------+-------------+-----------+---------------------+-----+-------+---------+
| 1 | 1 | NULL | NULL | 0 | NULL | NULL | NULL | NULL | ^SELECT.*FOR UPDATE$ | NULL | 0 | CASELESS | NULL | NULL | 1 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | 1 | NULL |
| 2 | 1 | NULL | NULL | 0 | NULL | NULL | NULL | NULL | ^SELECT | NULL | 0 | CASELESS | NULL | NULL | 2 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | 1 | NULL |
+---------+--------+----------+------------+--------+-------------+------------+------------+--------+----------------------+---------------+----------------------+--------------+---------+-----------------+-----------------------+-----------+--------------------+---------------+-----------+---------+---------+-------+-------------------+----------------+------------------+-----------+--------+-------------+-----------+---------------------+-----+-------+---------+
2 rows in set (0.00 sec)
Admin>
4、设置用户
前文已经将服务端口从ProxySQL安装好之后默认的6033修改为3306了。但此时还不能使用,需要配置账号。目前版本的ProxySQL不支持前后端分离账号,ProxySQL所有的认证体系都是同一套。
这意味着:
INSERT INTO mysql_users(username,password,default_hostgroup) VALUES ('admin','wp123456',1);
LOAD MYSQL USERS TO RUNTIME;
SAVE MYSQL USERS TO DISK;
这里就添加了一个用户名为admin和密码是wp123456的用户。配置完毕后,执行如下命令,验证是否正常:
SELECT * FROM mysql_users;
显示结果类似如下则表示正常:
Admin> SELECT * FROM mysql_users;
+----------+----------+--------+---------+-------------------+----------------+---------------+------------------------+--------------+---------+----------+-----------------+---------+
| username | password | active | use_ssl | default_hostgroup | default_schema | schema_locked | transaction_persistent | fast_forward | backend | frontend | max_connections | comment |
+----------+----------+--------+---------+-------------------+----------------+---------------+------------------------+--------------+---------+----------+-----------------+---------+
| admin | wp123456 | 1 | 0 | 1 | NULL | 0 | 1 | 0 | 1 | 1 | 10000 | |
+----------+----------+--------+---------+-------------------+----------------+---------------+------------------------+--------------+---------+----------+-----------------+---------+
1 row in set (0.00 sec)
Admin>
另外请注意,ProxySQL是支持使用hash后的密码而不是明文密码的,相关配置请参考ProxySQL官网的文档。
5、健康检查
本文使用AWS Aurora MySQL作为后单数据库,Aurora本身是以一个主节点一个只读节点的方式作为高可用的,且Aurora的Endpoint名称是自动做failover切换的。因此,无需使用ProxySQL自带的健康检查和切换功能。此部分配置可以跳过。
6、验证登录
现在退出ProxySQL的管理员console,使用普通的MySQL客户端连接到ProxySQL所在节点的IP的3306端口,测试下访问。命令如下。
mysql -h proxysql的服务器ip -uadmin -pwp123456
返回结果如下则表示成功。
[ec2-user@ip-172-31-11-6 ~]$ mysql -h 172.31.31.146 -uadmin -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 40
Server version: 5.5.30 (ProxySQL)
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
MySQL [(none)]>
则表示连接成功且可以正常执行查询。
1、安装Sysbench
启动一个新的EC2应用服务器,独立于ProxySQL的EC2,作为专门的应用客户端施加压力。系统启动完成后,以root身份执行如下命令:
amazon-linux-extras install epel
yum update -y
reboot
执行reboot的原因是确保内核等均为最新。
yum install sysbench mysql -y
安装Sysbench完成。
执行性能测试前请注意,AWS上不同规格的RDS承载能力是不一样的。最大连接数可以通过登录Aurora MySQL后使用如下命令查询。
show variables where Variable_name like "%conn%";
例如本次实验使用的规格较小,返回信息如下,其中最大连接数为90。
MySQL [(none)]> show variables where Variable_name like "%conn%";
+-----------------------------------------------+-----------------+
| Variable_name | Value |
+-----------------------------------------------+-----------------+
| aurora_max_connections_limit | 16000 |
| character_set_connection | utf8 |
| collation_connection | utf8_general_ci |
| connect_timeout | 10 |
| disconnect_on_expired_password | ON |
| init_connect | |
| max_connect_errors | 100 |
| max_connections | 90 |
| max_user_connections | 0 |
| performance_schema_session_connect_attrs_size | 0 |
+-----------------------------------------------+-----------------+
10 rows in set (0.00 sec)
MySQL [(none)]>
测试中请注意,这个参数可以调大,但是默认数值根据AWS的RDS机型规格不一样,默认值有所不同。请注意后续读写压力测试时候的最大连接数都不要超过这个界限。ProxySQL内置的默认最大连接数是2048,但是Proxy后端的Aurora MySQL最大连接只有90,因此在不修改90的情况下,在后续的测试中只使用50个并发来做压力测试。
2、准备测试数据
在压力测试节点上,运行如下命令建立测试数据,其中的host地址需要替换为ProxySQL所在的内网IP地址。EC2的内网IP地址是不会改变的,因此可以不使用域名,直接使用IP地址。
sysbench --db-driver=mysql --mysql-host=172.31.31.146 --mysql-port=3306 --mysql-user=admin --mysql-password=wp123456 --mysql-db=wordpress --table_size=10000 --tables=20 --threads=2 oltp_read_write prepare
这里需要注意的是,执行插入测试数据时候,会写入大量的数据,此时数据是写入到主节点的,并通过Aurora的复制技术传输到只读节点。由此,主节点和辅助节点都有一定的CPU占用,这是正常的。数据导入完成后,等待一段时间,让CPU和负载逐渐平缓,并记录测试开始时间,稍后将从RDS控制面板上查询数据库性能。
2、写入数据测试
在压力测试节点上,运行如下命令:
sysbench --db-driver=mysql --mysql-host=172.31.31.146 --mysql-port=3306 --mysql-user=admin --mysql-password=changeme --mysql-db=wordpress --table_size=10000 --tables=20 --events=0 --time=300 --threads=50 --report-interval=10 oltp_write_only run
运行测试300秒结束后,通过AWS RDS的控制台上的监控数据可以看出,写入节点产生了50个并发连接,且在300秒时间内对CPU造成了较大的压力,写入任务顺利的完成。如下截图。
Admin> select * from stats_mysql_processlist limit 10;
+----------+-----------+-------+-----------+--------------+----------+-----------+---------------+------------+----------------------------------------------------------------------------+----------+---------+---------+-----------------------------------------------------------+--------------+---------------+
| ThreadID | SessionID | user | db | cli_host | cli_port | hostgroup | l_srv_host | l_srv_port | srv_host | srv_port | command | time_ms | info | status_flags | extended_info |
+----------+-----------+-------+-----------+--------------+----------+-----------+---------------+------------+----------------------------------------------------------------------------+----------+---------+---------+-----------------------------------------------------------+--------------+---------------+
| 0 | 52 | admin | wordpress | 172.31.29.78 | 60924 | 2 | 172.31.31.146 | 43224 | proxy-test-cluster.cluster-ro-cfvonviibzua.rds.cn-north-1.amazonaws.com.cn | 3306 | Prepare | 1 | SELECT c FROM sbtest20 WHERE id=? | 0 | NULL |
| 3 | 53 | admin | wordpress | 172.31.29.78 | 60928 | 2 | 172.31.31.146 | 43214 | proxy-test-cluster.cluster-ro-cfvonviibzua.rds.cn-north-1.amazonaws.com.cn | 3306 | Execute | 2 | SELECT c FROM sbtest16 WHERE id=? | 0 | NULL |
| 1 | 54 | admin | wordpress | 172.31.29.78 | 60926 | 2 | 172.31.31.146 | 43222 | proxy-test-cluster.cluster-ro-cfvonviibzua.rds.cn-north-1.amazonaws.com.cn | 3306 | Execute | 0 | SELECT c FROM sbtest13 WHERE id=? | 0 | NULL |
| 1 | 55 | admin | wordpress | 172.31.29.78 | 60930 | 2 | 172.31.31.146 | 43244 | proxy-test-cluster.cluster-ro-cfvonviibzua.rds.cn-north-1.amazonaws.com.cn | 3306 | Execute | 1 | SELECT c FROM sbtest2 WHERE id=? | 0 | NULL |
| 1 | 56 | admin | wordpress | 172.31.29.78 | 60932 | 2 | 172.31.31.146 | 43384 | proxy-test-cluster.cluster-ro-cfvonviibzua.rds.cn-north-1.amazonaws.com.cn | 3306 | Execute | 3 | SELECT c FROM sbtest6 WHERE id BETWEEN ? AND ? ORDER BY c | 0 | NULL |
| 2 | 57 | admin | wordpress | 172.31.29.78 | 60934 | 2 | 172.31.31.146 | 43390 | proxy-test-cluster.cluster-ro-cfvonviibzua.rds.cn-north-1.amazonaws.com.cn | 3306 | Execute | 0 | SELECT c FROM sbtest20 WHERE id=? | 0 | NULL |
| 1 | 58 | admin | wordpress | 172.31.29.78 | 60936 | 2 | 172.31.31.146 | 43240 | proxy-test-cluster.cluster-ro-cfvonviibzua.rds.cn-north-1.amazonaws.com.cn | 3306 | Execute | 3 | SELECT c FROM sbtest5 WHERE id=? | 0 | NULL |
| 0 | 59 | admin | wordpress | 172.31.29.78 | 60938 | 2 | NULL | NULL | NULL | NULL | Sleep | 0 | NULL | NULL | NULL |
| 3 | 60 | admin | wordpress | 172.31.29.78 | 60940 | 1 | 172.31.31.146 | 49642 | proxy-test-cluster.cluster-cfvonviibzua.rds.cn-north-1.amazonaws.com.cn | 3306 | Execute | 0 | COMMIT | 0 | NULL |
| 2 | 61 | admin | wordpress | 172.31.29.78 | 60942 | 2 | NULL | NULL | NULL | NULL | Sleep | 0 | NULL | NULL | NULL |
+----------+-----------+-------+-----------+--------------+----------+-----------+---------------+------------+----------------------------------------------------------------------------+----------+---------+---------+-----------------------------------------------------------+--------------+---------------+
10 rows in set (0.01 sec)
Admin>
保持Sysbench一直处于read_only测试的情况下,反复多次执行上一条语句查询当前正在执行的SQL,且限制输出10行。反复执行几次,就可以看到其中的输出内容包括如下一条:
| 3 | 60 | admin | wordpress | 172.31.29.78 | 60940 | 1 | 172.31.31.146 | 49642 | proxy-test-cluster.cluster-cfvonviibzua.rds.cn-north-1.amazonaws.com.cn | 3306 | Execute | 0 | COMMIT | 0 | NULL |
这条命令的info字段显示正在执行的命令是commit命令,就是为什么部分流量被发往主节点的原因。因为Sysbench是一个完整的测试工具,其中使用了在只读测试中,也包含了commit语句,因此根据前文Proxy配置的规则,commit语句将被发往主节点进行解析。所以,才造成了在监控数据上看,主节点也拥有了50个并发连接,但是大部分压力都是在只读节点的原因。
由于Readonly测试不会写入数据,因此在跑Sysbench脚本时候,执行commit命令其实是没有意义的。因此可以禁用掉事务,进行完全的只读查询。
4、不带事务的只读测试
由于ProxySQL还会对节点保持长连接,因此我们需要先重启服务重置连接,以获得一个干净的环境,便于更简单的通过监控数据来判定流量是否分离成功。然后再进行下一个测试。登录到ProxySQL的服务器,执行如下命令:
mysql -u proxyadmin -pproxyadmin -h 127.0.0.1 -P6032 --prompt='Admin>
PROXYSQL RESTART;
由此将通过重启服务重置所有连接。重置完毕后,在等待一段时间(5-10分钟),等到AWS RDS控制台上的监控数据已经恢复到较低水平后,再发起下一个测试。由此,将可以更简单的快速识别流量是否是读写分类正常施压造成的。
这里对上一个只读测试脚本,增加–skip_trx=on的参数。到压力服务器上,执行如下命令:
sysbench --db-driver=mysql --mysql-host=172.31.31.146 --mysql-port=3306 --mysql-user=admin --mysql-password=changeme --mysql-db=wordpress --table_size=10000 --tables=20 --events=0 --time=300 --threads=50 --report-interval=10 --skip_trx=on oltp_read_only run
测试后,再次通过RDS控制台检查主实例和只读实例的负载,可以发现负载被完全路由到了只读实例,主实例不会承担负载,也不会有建立连接。只读实例的负载如下截图。
使用Session Manager登录EC2 Linux
使用Session Manager登录位于内网的EC2的RDP远程桌面
使用EC2 Instance Connect网页界面SSH工具登陆EC2 Linux
如何在IAM上生成AKSK
Windows和Linux安装CloudWatch Agent增加内存和磁盘监控
使用ec2-instance-selector查询规格
多种方式查询最新AMI
EC2 Linux 安装Mate GUI
CentOS安装ENA驱动
Level 200系列:
EKS 101 & 201 系列合集(1.27版本于2023-07测试通过)
ECS 201系列
Kinesis 101系列三部曲
保护API Gateway安全三部曲
查询各服务IP范围
在EC2 Windows上通过WSL运行Linux
Level 300系列:
Gateway Load Balancer 集中式和分布式流量检测
Quickstart
更多文章请使用站内搜索输入服务名称查找