如何测试MaxScale负载均衡?MariaDB主从查询分发异常排查
MariaDB主从+MaxScale架构下,SELECT查询分发不均的问题排查与测试方案
我搭建了MariaDB主从架构并配置了MaxScale,想测试MaxScale是否能将SELECT查询分发到多个副本库,但当前测试结果显示查询只转发到其中一个副本库,求正确的测试方法。
服务器信息
- MariaDB 10.11
- MaxScale 23.02.4
- masterDB: 192.168.30.140
- replicaDB1: 192.168.30.141
- replicaDB2: 192.168.30.142
- replicaDB3: 192.168.30.143
- maxscale: 192.168.30.145
- client: 192.168.30.160
- 端口映射:3309指向主库,3310指向副本库
MaxScale配置
[maxscale] threads=auto [MariaDB-Monitor] type=monitor module=mariadbmon servers=masterDB, replicaDB1, replicaDB2, replicaDB3 user=monitor password=alj123 monitor_interval=2s [masterDB] type=server address=192.168.30.140 port=3306 protocol=MariaDBBackend proxy_protocol=true persistpoolmax=100 persistmaxtime=3600s monitoruser=monitor monitorpw=alj123 max_routing_connections=1000 [replicaDB1] type=server address=192.168.30.141 port=3306 protocol=MariaDBBackend proxy_protocol=true persistpoolmax=100 persistmaxtime=3600s monitoruser=monitor monitorpw=alj123 max_routing_connections=1000 [replicaDB2] type=server address=192.168.30.142 port=3306 protocol=MariaDBBackend proxy_protocol=true persistpoolmax=100 persistmaxtime=3600s monitoruser=monitor monitorpw=alj123 max_routing_connections=1000 [replicaDB3] type=server address=192.168.30.143 port=3306 protocol=MariaDBBackend proxy_protocol=true persistpoolmax=100 persistmaxtime=3600s monitoruser=monitor monitorpw=alj123 max_routing_connections=1000 # 写服务定义 [Write-Service] type=service router=readconnroute router_options=master, slave servers=masterDB user=maxscale password=alj123 max_connections=100 # 读服务定义 [Read-Service] type=service router=readconnroute router_options=slave servers=replicaDB1, replicaDB2, replicaDB3 user=read password=alj123 max_connections=100 # 写请求监听器 [Write-Listener] type=listener service=Write-Service protocol=MariaDBClient port=3309 address=0.0.0.0 proxy_protocol_networks=192.168.30.145/24 # 读请求监听器 [Read-Listener] type=listener service=Read-Service protocol=MariaDBClient port=3310 address=0.0.0.0 proxy_protocol_networks=192.168.30.145/24
当前测试脚本(PHP)
<?php $start = (new DateTime())->getTimestamp(); echo "start= $start" . PHP_EOL; for ($i=0; $i<40000; $i++) { $mysqli = new mysqli("p:192.168.30.145", "client", "alj123", "TOPGUN", "3310"); $mysqli->query("SELECT pilot from TOPGUN.pilots"); $sql = "SELECT @@hostname"; $result = $mysqli->query($sql); if ($result->num_rows > 0) { $row = $result->fetch_assoc(); echo "DB主机: " . $row['@@hostname'] . PHP_EOL; } else { echo "无法获取DB主机信息"; } $result->free(); $mysqli->close(); unset($tmp, $row, $result, $mysqli); } $end = (new DateTime())->getTimestamp(); echo '耗时= ' . ($end - $start) . '秒' . PHP_EOL; ?>
问题分析与解决方案
1. 配置问题排查
你的Read-Service使用readconnroute路由器,默认负载均衡策略是轮询(roundrobin),但需确认以下几点:
- 检查MaxScale监控状态,确保三个副本库都被标记为
Slave且处于Running状态:
执行MaxScale命令:
输出中每个replicaDB的状态需包含maxctrl list serversSlave, Running,若副本状态异常,MaxScale不会将请求分发过去。 - 显式指定负载均衡策略:在
Read-Service的router_options中添加roundrobin,确保策略生效,修改后为:
修改后重启MaxScale:router_options=slave,roundrobinsystemctl restart maxscale
2. 测试脚本的问题
单线程循环创建连接的方式无法模拟真实并发场景,且脚本中使用了持久连接(p:前缀),持久连接会被MaxScale复用,导致同一连接的请求都发到同一个副本。
改进后的测试方法:
- 多进程/多线程测试:MaxScale的负载均衡是针对不同连接的,多进程能模拟真实并发,示例PHP多进程脚本:
<?php $processCount = 10; // 启动10个测试进程 $requestsPerProcess = 4000; // 每个进程发起4000次请求 for ($p = 0; $p < $processCount; $p++) { $pid = pcntl_fork(); if ($pid == -1) { die("进程创建失败"); } elseif ($pid == 0) { // 子进程逻辑 for ($i=0; $i<$requestsPerProcess; $i++) { $mysqli = new mysqli("192.168.30.145", "client", "alj123", "TOPGUN", "3310"); if ($mysqli->connect_error) { echo "连接失败: " . $mysqli->connect_error . PHP_EOL; continue; } $result = $mysqli->query("SELECT @@hostname"); if ($result) { $row = $result->fetch_assoc(); echo "进程{$p} - DB主机: " . $row['@@hostname'] . PHP_EOL; $result->free(); } $mysqli->close(); } exit(); } } // 等待所有子进程结束 while (pcntl_waitpid(0, $status) != -1); echo "所有测试完成" . PHP_EOL; ?> - 移除持久连接前缀:去掉脚本中
mysqli连接地址的p:,使用短连接,让每个请求创建独立连接,MaxScale会为新连接分配不同副本。 - 手动多次测试:用mysql客户端多次执行查询,观察返回的主机名是否轮流切换:
# 重复执行该命令,查看输出变化 mysql -h 192.168.30.145 -P 3310 -u client -palj123 -e "SELECT @@hostname"
3. 连接池配置调整
persistpoolmax=100和persistmaxtime=3600s会让MaxScale复用连接,若测试时连接未释放,可能导致请求集中在某个副本。可临时降低persistmaxtime,或测试前重启MaxScale清空连接池。
验证步骤
- 执行
maxctrl list servers确认所有副本状态正常。 - 修改
Read-Service的router_options为slave,roundrobin,重启MaxScale。 - 使用多进程脚本或手动多次执行mysql命令,观察返回的主机名是否均匀分布在三个副本上。
内容的提问来源于stack exchange,提问作者hekke
相关产品推荐
相关产品推荐

