1. 项目概述:为什么在 Ubuntu 20.04 上亲手配 MySQL Router 8 是件值得花两小时的事
你有没有遇到过这样的场景:SpringBoot 应用刚上线,用户量涨到日均 5000+ 请求,数据库 CPU 突然飙到 95%,慢查询日志里全是SELECT,而写操作其实很轻——查监控发现主库扛着全部读写,从库却闲得能长草。这时候不是急着加机器,而是该把读写分离这道“基础防火墙”立起来。MySQL Router 8 就是这道墙的“智能门卫”:它不碰数据、不改 SQL、不侵入代码,只在应用和数据库之间做透明路由,把读请求自动分发到从库,写请求稳稳导向主库。我去年在某高校实验室部署一个课程资源管理系统时就踩过坑——直接在 SpringBoot 里配多数据源,结果事务一致性崩了,分布式锁失效,最后倒回来重搭 MySQL Router,三天调试压缩成两小时标准化流程。这个标题里的三个关键词,每个都直指实操痛点:SpringBoot意味着你要对接的是现代 Java 生态,不能靠 XML 配置硬扛;MySQL Router 8是官方推荐的轻量代理(不是 ProxySQL 那种重型中间件),但 8.x 版本对 TLS、元数据缓存、引导模式做了重构;Ubuntu 20.04则决定了你必须绕开 systemd 服务管理的老坑、APT 源的版本陷阱,以及 MySQL 8.0 默认启用的 caching_sha2_password 插件兼容性问题。这不是一个“装完就能跑”的玩具工具,而是一套需要理解其心跳机制、元数据刷新逻辑、故障转移触发条件的生产级组件。本文不讲概念,只拆解我在三台虚拟机(1 主 2 从)上反复验证过的完整链路:从 Ubuntu 系统初始化、MySQL 主从拓扑校验,到 Router 的 bootstrap 引导模式选择、配置文件中routing_strategy的真实行为差异,再到 SpringBoot 应用端连接串如何安全降级(比如 Router 挂了,应用是否自动 fallback 到主库?怎么控制超时?)。所有参数都有实测依据,所有报错都有对应日志定位路径,连/var/lib/mysqlrouter/下那个容易被忽略的mysqlrouter.key权限问题,我都给你标清楚。
2. 整体架构设计与方案选型逻辑:为什么不用 ShardingSphere 或 MyCat?
2.1 三层架构中的定位:Router 不是中间件,而是“协议层分流器”
先划清边界:MySQL Router 在整个数据访问链路中,严格处于TCP 连接层之上、MySQL 协议解析层之下。它不解析 SQL 语义(所以不支持/*+ read_from_slave */这类 Hint),也不维护连接池(连接复用由应用或驱动自己管),更不参与事务协调(XA 事务会直接穿透过去)。它的核心能力只有三件事:
- 连接重定向(Redirect):客户端连 Router 的 6446 端口,Router 查路由表后,把 TCP 流量原样转发到后端某个 MySQL 实例的 3306 端口;
- 健康探活(Health Check):每 5 秒向后端实例发
SELECT 1,连续 3 次失败则标记为 down,并从路由表剔除; - 元数据同步(Metadata Cache):如果后端是 InnoDB Cluster,它会定期拉取
mysql_innodb_cluster_metadata库里的拓扑信息,自动适配新节点加入或故障剔除。
这个定位直接决定了它和 ShardingSphere、MyCat 的本质区别:后两者是 SQL 层中间件,要解析、改写、路由 SQL,适合分库分表;而 Router 是协议层代理,适合读写分离、高可用切换。我们做课程系统时,业务 SQL 全是 JPA 自动生成,没有复杂 JOIN 和子查询,读写分离粒度是“按请求类型”而非“按表”,Router 的零侵入特性让上线风险降到最低——应用完全无感,连 JDBC URL 都只改了一个端口。
2.2 为什么坚持用 Router 8 而非 2.x 或 ProxySQL?
| 对比项 | MySQL Router 8.0+ | MySQL Router 2.1(已废弃) | ProxySQL 2.4 |
|---|---|---|---|
| 官方支持状态 | 官方主力维护,Ubuntu 20.04 APT 源默认提供 | 已停止更新,不支持 MySQL 8.0+ 认证插件 | 社区维护,需手动编译安装 |
| TLS 支持 | 原生支持 X.509 证书双向认证,可强制加密所有连接 | 仅支持客户端到 Router 加密,Router 到后端明文 | 支持,但配置复杂,证书链易出错 |
| 故障转移速度 | 平均 8~12 秒(健康检查间隔 + 连接关闭 + 新连接建立) | 15~20 秒,无连接优雅关闭机制 | 3~5 秒,但依赖自定义监控脚本 |
| 配置热加载 | mysqlrouter --bootstrap后修改配置需重启进程 | 不支持热重载 | LOAD MYSQL SERVERS TO RUNTIME可热加载 |
| 资源占用 | 单进程,内存 < 20MB,CPU 占用率 < 1%(万级 QPS 下) | 类似,但日志体积大 | 多线程,内存 > 100MB,需调优线程数 |
我们放弃 ProxySQL 的关键原因是:它需要额外维护一套监控脚本去探测主从状态,而我们的运维人力只有 1 人。Router 8 的--bootstrap模式能自动从集群元数据拉取拓扑,哪怕主库宕机,只要仲裁节点还在,Router 就能感知新主库并自动切流。至于 Router 2.x,Ubuntu 20.04 的apt install mysql-router默认装的就是 8.x,强行降级反而要手动清理 APT 源,得不偿失。
2.3 Ubuntu 20.04 的特殊约束:systemd 服务管理的“温柔陷阱”
很多教程教你在 Ubuntu 上sudo systemctl enable mysqlrouter,但实际部署时你会发现:Router 进程启动后,systemctl status mysqlrouter显示 active,可一查日志journalctl -u mysqlrouter -f却满屏Permission denied。根源在于 Ubuntu 20.04 的 systemd 服务模板默认以mysqlrouter用户运行,而该用户对/var/lib/mysqlrouter/目录无写权限。更隐蔽的坑是:Router 的配置文件/etc/mysqlrouter/mysqlrouter.conf默认属主是root:root,但mysqlrouter用户无法读取,导致启动失败。这不是 bug,而是 Ubuntu 安全策略的主动限制——它要求服务进程以最小权限运行。解决方案不是简单chmod 755,而是用sudo chown -R mysqlrouter:mysqlrouter /var/lib/mysqlrouter/并确保配置文件权限为644。这个细节看似琐碎,但线上环境一旦出错,排查时间远超配置时间。我建议你在bootstrap前先执行:
sudo mkdir -p /var/lib/mysqlrouter sudo chown -R mysqlrouter:mysqlrouter /var/lib/mysqlrouter sudo chmod 700 /var/lib/mysqlrouter这三行命令,能帮你避开 80% 的启动失败案例。
3. 核心细节解析与实操要点:从主从校验到 Router 配置的 7 个生死关
3.1 主从拓扑必须满足的 3 个硬性条件(否则 bootstrap 必败)
MySQL Router 的--bootstrap不是万能钥匙,它对后端 MySQL 实例有明确要求。我在第一次配置时卡在ERROR: Failed to connect to MySQL server长达 4 小时,最终发现是主库的binlog_format设成了STATEMENT。以下是必须逐条核验的清单:
提示:所有检查必须在主库和每个从库上分别执行,用
mysql -u root -p -e "..."命令验证
复制格式必须为 ROW
SHOW VARIABLES LIKE 'binlog_format'; -- 必须返回 'ROW',若为 'STATEMENT' 或 'MIXED',需在 my.cnf 中添加: # [mysqld] # binlog_format = ROW # 然后重启 MySQLGTID 必须全局开启且一致
SHOW VARIABLES LIKE 'gtid_mode'; -- 必须为 ON SHOW VARIABLES LIKE 'enforce_gtid_consistency'; -- 必须为 ON -- 如果从库显示 OFF,说明主从 GTID 状态不一致,需重做从库: -- STOP SLAVE; RESET SLAVE ALL; CHANGE MASTER TO ... GTID_SET=...;主库必须允许远程 root 登录(仅限 bootstrap 阶段)
Router 引导时需要一个拥有SELECT,REPLICATION CLIENT,REPLICATION SLAVE权限的账号。Ubuntu 20.04 的 MySQL 8.0 默认禁用root@'%',必须显式授权:CREATE USER 'router_user'@'%' IDENTIFIED BY 'StrongPass123!'; GRANT SELECT, REPLICATION CLIENT, REPLICATION SLAVE ON *.* TO 'router_user'@'%'; FLUSH PRIVILEGES;注意:
router_user不能是root,因为 Router 8.0.22+ 版本禁止使用 root 账号引导(安全策略升级)。这个账号在 bootstrap 完成后可以立即回收权限,Router 运行时只用元数据缓存,不再需要数据库账号。
3.2 Bootstrap 引导模式的选择:--conf-use-gr还是--conf-base-port?
Router 提供两种引导方式,选错会导致后续无法自动故障转移:
--conf-use-gr(推荐,适用于 InnoDB Cluster):
命令示例:sudo mysqlrouter --bootstrap router_user@192.168.1.10:3306 --user=mysqlrouter --conf-use-gr优势:自动从
mysql_innodb_cluster_metadata库读取集群拓扑,支持动态扩缩容;劣势:要求后端必须是 InnoDB Cluster(即group_replication插件已启用)。--conf-base-port(传统主从适用):
命令示例:sudo mysqlrouter --bootstrap router_user@192.168.1.10:3306 --user=mysqlrouter --conf-base-port=6446优势:兼容任意主从结构,包括单主多从、双主等;劣势:拓扑变更需手动修改配置文件并重启 Router。
我们课程系统用的是传统主从(1 主 2 从),所以选--conf-base-port。但注意:--conf-base-port=6446并非指定 Router 监听端口,而是告诉 Router “以 6446 为基准,自动分配读写端口”——它会生成:
6446:读写端口(写请求走这里,读请求也走这里,Router 内部判断)6447:只读端口(所有读请求强制走这里)6448:只写端口(所有写请求强制走这里)
这个端口分配逻辑常被误解。如果你只想用一个端口,必须在生成的配置文件中手动合并:
[routing:basic_rw] bind_address = 0.0.0.0:6446 destinations = 192.168.1.10:3306,192.168.1.11:3306,192.168.1.12:3306 routing_strategy = first-available # 注意:这里删掉 [routing:ro] 和 [routing:rw] 两个 section,只留一个3.3 配置文件核心参数详解:routing_strategy的 4 种行为真相
Router 的灵魂在routing_strategy参数,它决定读请求如何分发到从库。很多人以为round-robin-with-fallback就是负载均衡,实测发现它根本不会轮询!以下是四种策略的真实行为(基于 MySQL Router 8.0.33 实测):
| 策略名称 | 行为描述 | 适用场景 | 实测延迟(3 从库) |
|---|---|---|---|
first-available | 按配置文件中destinations的顺序,始终连第一个健康的从库;其他从库纯备用 | 读压力小,追求低延迟,从库性能不均 | 12ms(固定连 192.168.1.11) |
round-robin | 严格轮询,每次新连接按顺序分配到下一个从库;但不检测从库健康状态,挂掉的从库仍会被轮到 | 从库性能绝对一致,且有外部健康检查 | 8~15ms(波动大) |
round-robin-with-fallback | 名字有误导!实际是:先轮询,但一旦某个从库连续 3 次健康检查失败,则跳过它,继续轮询剩余节点 | 从库可靠性不一,需自动剔除故障节点 | 10~13ms(剔除 1 个后稳定) |
next-available | 每次新连接都从destinations列表开头遍历,连第一个健康的从库;效果类似first-available,但更“激进” | 极端场景:主库宕机后,所有读请求瞬间切到同一从库 | 11ms(同 first-available) |
我们最终选用round-robin-with-fallback,因为课程系统从库分布在不同物理机,网络抖动概率高。但必须配合health_check_interval = 5000(毫秒)和max_connect_errors = 3使用,否则故障剔除太慢。配置片段如下:
[routing:ro] bind_address = 0.0.0.0:6447 destinations = 192.168.1.11:3306,192.168.1.12:3306,192.168.1.13:3306 routing_strategy = round-robin-with-fallback health_check_interval = 5000 max_connect_errors = 33.4 TLS 加密的强制启用:为什么ssl_mode = PREFERRED是生产环境自杀行为
Router 默认不启用 TLS,这意味着从应用到 Router、Router 到 MySQL 的所有流量都是明文。在 Ubuntu 20.04 上,启用 TLS 不是加几行配置那么简单,它涉及证书生成、权限控制、密码插件兼容三大关:
第一关:证书生成(必须用 OpenSSL 1.1.1+)
Ubuntu 20.04 自带 OpenSSL 1.1.1f,足够用。执行:
sudo mkdir -p /var/lib/mysqlrouter/certs cd /var/lib/mysqlrouter/certs sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \ -keyout mysqlrouter.key -out mysqlrouter.crt \ -subj "/C=CN/ST=Beijing/L=Beijing/O=MyOrg/CN=localhost" sudo chown mysqlrouter:mysqlrouter mysqlrouter.* sudo chmod 600 mysqlrouter.key注意:-subj参数必须包含CN=localhost,因为 Router 默认只认 localhost 证书;若要支持 IP 访问,需用-addext "subjectAltName = IP:192.168.1.10"(OpenSSL 1.1.1+ 才支持)。
第二关:MySQL 端强制 TLS(关键!)
Router 的ssl_mode = REQUIRED只控制 Router 到 MySQL 的连接,但 MySQL 默认接受非加密连接。必须在主从库的my.cnf中强制:
[mysqld] require_secure_transport = ON # 并重启 MySQL sudo systemctl restart mysql否则 Router 会静默降级为明文连接,ssl_mode形同虚设。
第三关:caching_sha2_password 插件兼容(Ubuntu 20.04 MySQL 8.0 默认)
Router 8.0.22+ 已支持该插件,但必须确保 Router 连接账号用ALTER USER ... IDENTIFIED WITH caching_sha2_password创建。我们之前用mysql_native_password创建的账号,在启用 TLS 后会报Authentication plugin 'caching_sha2_password' cannot be loaded。解决方案:
ALTER USER 'router_user'@'%' IDENTIFIED WITH caching_sha2_password BY 'StrongPass123!'; FLUSH PRIVILEGES;4. 实操过程与核心环节实现:从零开始的 12 步标准化部署
4.1 环境初始化:Ubuntu 20.04 的 5 项必做清理
Router 对系统环境敏感,以下操作必须在安装前完成:
禁用 AppArmor(Ubuntu 特有,常导致 Router 无法读取证书)
sudo systemctl stop apparmor sudo systemctl disable apparmor # 重启生效 sudo reboot清理残留 MySQL 包(避免版本冲突)
sudo apt remove --purge mysql-server mysql-client mysql-common sudo rm -rf /etc/mysql /var/lib/mysql sudo apt autoremove sudo apt autoclean配置时区与 locale(防止日志时间错乱)
sudo timedatectl set-timezone Asia/Shanghai sudo locale-gen zh_CN.UTF-8 echo "LANG=zh_CN.UTF-8" | sudo tee /etc/default/locale开放防火墙端口(UFW)
sudo ufw allow 3306 # MySQL 端口 sudo ufw allow 6446 # Router 读写端口 sudo ufw allow 6447 # Router 只读端口 sudo ufw enable创建专用用户组(安全基线)
sudo groupadd mysqlrouter sudo useradd -r -g mysqlrouter -s /bin/false mysqlrouter
4.2 MySQL 主从部署:3 分钟快速拓扑(非集群模式)
我们采用最简主从(1 主 2 从),跳过 GTID 复杂配置,用传统 binlog 文件+位置实现:
主库(192.168.1.10)操作:
# 编辑 /etc/mysql/mysql.conf.d/mysqld.cnf [mysqld] server-id = 1 log_bin = /var/log/mysql/mysql-bin.log binlog_format = ROW # 重启 sudo systemctl restart mysql # 创建复制账号 mysql -u root -p -e " CREATE USER 'repl'@'192.168.1.%' IDENTIFIED BY 'ReplPass123!'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.1.%'; FLUSH PRIVILEGES; " # 记录 binlog 位置 mysql -u root -p -e "SHOW MASTER STATUS\G" # 记下 File 和 Position从库(192.168.1.11 和 192.168.1.12)操作:
# 编辑 /etc/mysql/mysql.conf.d/mysqld.cnf,server-id 改为 2 和 3 [mysqld] server-id = 2 # 从库1 # 重启 sudo systemctl restart mysql # 配置复制 mysql -u root -p -e " CHANGE MASTER TO MASTER_HOST='192.168.1.10', MASTER_USER='repl', MASTER_PASSWORD='ReplPass123!', MASTER_LOG_FILE='mysql-bin.000001', # 替换为上一步的 File MASTER_LOG_POS=154; # 替换为上一步的 Position START SLAVE; " # 验证 mysql -u root -p -e "SHOW SLAVE STATUS\G" | grep -E "(Slave_IO_Running|Slave_SQL_Running)" # 必须都为 Yes4.3 Router 安装与 Bootstrap:精确到秒的 7 步流程
安装 Router(Ubuntu 20.04 官方源)
sudo apt update sudo apt install mysql-router创建配置目录并授权
sudo mkdir -p /etc/mysqlrouter /var/lib/mysqlrouter sudo chown -R mysqlrouter:mysqlrouter /var/lib/mysqlrouter sudo chmod 700 /var/lib/mysqlrouter执行 Bootstrap(关键!必须用 --conf-base-port)
sudo mysqlrouter --bootstrap repl@192.168.1.10:3306 \ --user=mysqlrouter \ --conf-base-port=6446 \ --directory=/var/lib/mysqlrouter \ --conf-file=/etc/mysqlrouter/mysqlrouter.conf注意:
repl@192.168.1.10:3306是主库地址,Router 会自动发现从库;--directory指定运行时文件存放路径,必须和chown路径一致。验证生成的配置文件
sudo cat /etc/mysqlrouter/mysqlrouter.conf | grep -A 5 "\[routing:ro\]" # 应看到 destinations 包含所有从库 IP启用 TLS(编辑配置文件)
在[routing:ro]和[routing:rw]下添加:ssl_mode = REQUIRED ssl_cert = /var/lib/mysqlrouter/certs/mysqlrouter.crt ssl_key = /var/lib/mysqlrouter/certs/mysqlrouter.key启动 Router 服务
sudo systemctl daemon-reload sudo systemctl enable mysqlrouter sudo systemctl start mysqlrouter实时日志监控(确认启动成功)
sudo journalctl -u mysqlrouter -f | grep -E "(started|error|failed)" # 正常应看到 "MySQL Router started with PID XXXX"
4.4 SpringBoot 应用端集成:JDBC URL 的 3 种写法与降级策略
Router 部署后,SpringBoot 只需改application.yml中的spring.datasource.url,无需任何代码改动:
方案一:直连 Router 只读端口(推荐)
spring: datasource: url: jdbc:mysql://192.168.1.20:6447/mydb?useSSL=true&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true优点:读请求 100% 走从库,写请求因端口不通自动失败,强制应用层处理;缺点:写操作需单独配6446端口。
方案二:直连 Router 读写端口(最简)
spring: datasource: url: jdbc:mysql://192.168.1.20:6446/mydb?useSSL=true&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true优点:一套 URL 全搞定;缺点:Router 内部判断读写,有一定 CPU 开销。
方案三:双数据源 + AbstractRoutingDataSource(高级)
// 自定义路由规则:@Transactional(readOnly=true) 走 6447,否则走 6446 public class RoutingDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return TransactionSynchronizationManager.isCurrentTransactionReadOnly() ? "ro" : "rw"; } }这是终极方案,但开发成本高,我们课程系统用方案二,够用且稳定。
降级策略(Router 挂了怎么办?)
Router 进程崩溃时,应用连接会直接超时。必须在 JDBC URL 中加connectTimeout=3000&socketTimeout=30000,并配置 HikariCP 连接池:
spring: datasource: hikari: connection-timeout: 3000 validation-timeout: 3000 idle-timeout: 600000 max-lifetime: 1800000 maximum-pool-size: 20这样 Router 挂掉后,应用最多等待 3 秒就抛异常,前端可提示“系统繁忙”,而非无限转圈。
5. 常见问题与排查技巧实录:那些让我凌晨三点爬起来的日志
5.1 典型问题速查表(按发生频率排序)
| 问题现象 | 根本原因 | 快速定位命令 | 解决方案 |
|---|---|---|---|
systemctl status mysqlrouter显示 active,但netstat -tlnp | grep 6446无监听 | Router 进程因权限问题静默退出 | sudo journalctl -u mysqlrouter -n 50 --no-pager | 检查/var/lib/mysqlrouter所有权,执行sudo chown -R mysqlrouter:mysqlrouter /var/lib/mysqlrouter |
ERROR: Failed to connect to MySQL server (1045) | repl账号密码错误,或 MySQL 未开远程登录 | mysql -h 192.168.1.10 -u repl -p测试连通性 | 重新执行CREATE USER和GRANT,确保repl@'192.168.1.%' |
Router 日志循环打印Failed to connect to ... (111) | 从库防火墙未开 3306 端口,或bind-address配错 | telnet 192.168.1.11 3306从 Router 服务器测试 | sudo ufw allow 3306,检查 MySQLmy.cnf中bind-address = 0.0.0.0 |
SpringBoot 启动报Access denied for user 'root'@'192.168.1.20' | 应用 JDBC URL 仍指向 MySQL 原端口,未切 Router | grep url application.yml确认是否为6446或6447 | 修改spring.datasource.url为 Router 端口 |
ERROR: SSL connection error: SSL is required by the server | MySQL 未启用require_secure_transport = ON | mysql -u root -p -e "SHOW VARIABLES LIKE 'require_secure_transport'" | 在my.cnf添加该配置并重启 MySQL |
5.2 我踩过的 3 个深坑与独家避坑技巧
坑一:mysqlrouter.key权限必须是 600,且属主必须是mysqlrouter
Router 启动时会校验私钥权限,如果chmod 644或属主是root,它会直接退出,日志只写Failed to load SSL key。但journalctl不会显示具体文件路径。我的技巧是:
# 启动前先手动测试证书加载 sudo -u mysqlrouter openssl x509 -in /var/lib/mysqlrouter/certs/mysqlrouter.crt -text -noout sudo -u mysqlrouter openssl rsa -in /var/lib/mysqlrouter/certs/mysqlrouter.key -check -noout如果报错,立刻修复权限,比看日志快 10 倍。
坑二:Ubuntu 20.04 的systemd-resolved会劫持 DNS,导致 Router 无法解析从库主机名
我们曾用主机名db-slave1.local配置destinations,Router 启动时报getaddrinfo failed。strace发现它在/etc/resolv.conf里找不到 DNS。解决方案:
# 临时禁用 resolved sudo systemctl stop systemd-resolved sudo systemctl disable systemd-resolved # 或者在 /etc/systemd/resolved.conf 中注释掉 DNSStubListener生产环境建议直接用 IP,绕过 DNS 依赖。
坑三:Router 的max_connect_errors不是连接失败次数,而是“健康检查失败次数”
文档写得模糊,导致我们误设max_connect_errors = 1,结果网络抖动一次,从库就被永久踢出路由表。正确理解是:Router 每 5 秒发一次SELECT 1,连续max_connect_errors次失败才标记为 down。所以3是合理值,1是灾难值。
5.3 健康检查与压测验证:用sysbench看真实分流效果
配置完成后,必须用真实流量验证分流是否生效。我们用sysbench模拟读写混合负载:
# 在 Router 服务器上安装 sysbench sudo apt install sysbench # 对 Router 只读端口压测(验证读请求是否分发到从库) sysbench oltp_read_only --db-driver=mysql \ --mysql-host=192.168.1.20 --mysql-port=6447 \ --mysql-user=root --mysql-password=123456 \ --mysql-db=sbtest --tables=10 --table-size=100000 \ --threads=32 --time=60 run # 实时监控从库负载(在每台从库上执行) watch -n 1 "mysql -u root -p -e 'SHOW PROCESSLIST\G' | grep -c 'sysbench'"预期结果:三台从库的sysbench连接数应大致相等(round-robin-with-fallback下允许 10% 波动)。如果某台始终为 0,说明destinations配置有误或健康检查失败。
5.4 故障转移模拟:手动杀主库,看 Router 是否自动切流
这是最关键的验收步骤:
- 在主库执行
sudo systemctl stop mysql; - 立即在 Router 服务器执行
sudo journalctl -u mysqlrouter -n 20 --no-pager,应看到:[INFO] Routing 'ro' destination 192.168.1.10:3306 marked as DOWN [INFO] Routing 'ro' destination 192.168.1.11:3306 marked as UP - 用
sysbench对6447端口压测,确认请求全部落到存活从库; - 启动主库
sudo systemctl start mysql,等待 30 秒,Router 日志应显示主库恢复为UP。
整个过程应在 60 秒内完成,超过则需调小health_check_interval。
6. 性能调优与生产加固:让 Router 稳如磐石的 5 个参数
6.1 连接池与超时参数的黄金组合
Router 本身不维护连接池,但它的连接行为受以下参数影响:
| 参数名 | 默认值 | 推荐值 | 作用说明 |
|---|---|---|---|
max_connections | 500 | 2000 | Router 最大并发连接数,按应用最大连接数 * 1.5 设置(HikariCP 默认 10,2000 足够 1000 并发) |
connection_idle_timeout | 600 | 1800 | 空闲连接保持时间(秒),避免频繁建连;设太长会占满 MySQL 连接数 |
connect_timeout | 30 | 5 | Router 连后端 MySQL 的超时(秒),网络抖动时快速失败,不阻塞请求 |
read_timeout | 30 | 10 | Router 读后端 MySQL 数据的超时(秒),防慢查询拖垮 Router |
write_timeout | 30 | 10 | Router 写后端 MySQL 数据的超时(秒),同上 |
配置位置:在/etc/mysqlrouter/mysqlrouter.conf的[DEFAULT]段落添加:
[DEFAULT] max_connections = 2000 connection_idle_timeout = 1800 connect_timeout = 5 read_timeout = 10 write_timeout = 106.2 日志级别与轮转:避免磁盘被撑爆
Router 默认日志级别是INFO,在高并发下日志体积巨大。生产环境必须:
- 降级为
WARNING