一次华为云MySQL连接超时问题的排查实录
上个月我们项目准备上线,前一天晚上做最后的压测,结果MySQL连接突然开始频繁超时。报错日志里堆满了Communications link failure,应用日志里每隔几秒就出现一次connect timeout。前一天还好好的,代码也没动过,怎么就炸了?
我们用的是华为云RDS for MySQL,应用部署在同区域的ECS上。最开始怀疑是RDS出了问题,登录控制台看了监控,CPU和内存都正常,连接数也没到上限。又检查了慢查询日志,没有任何异常记录。那问题大概率出在应用侧或者网络侧。
第一步,我直接在ECS上用了mysql命令行去连RDS,居然也连不上,卡住十几秒后报超时。这就排除了应用代码的问题。然后我telnet了RDS的内网IP和3306端口,端口是通的,说明安全组和网络ACL没拦。那就奇怪了,端口通但连接超时,像是握手阶段卡住了。
我又从另一台测试ECS去连,结果秒连成功。那问题就锁定在这台生产ECS上了。对比两台ECS的网络配置,子网一样,安全组一样,甚至连镜像版本都一样。唯一不同的是生产ECS挂载了额外的云硬盘,但这显然不相关。
怀疑过是ECS的TCP参数问题,检查了net.ipv4.tcp_keepalive_time和net.ipv4.tcp_syn_retries,都是默认值。还看了系统日志dmesg,没有任何报错。折腾了两个小时,毫无进展。
后来无意中看了一眼RDS的连接地址,我们用的是内网域名,不是IP。我试着在生产ECS上用nslookup解析这个域名,结果解析出来的IP是公网地址,而不是内网IP!难怪连接超时——流量绕到了公网,而安全组对公网访问是有限制的,加上公网延迟高,自然握手失败。
为什么会解析到公网IP?因为RDS的内网域名解析依赖VPC的DNS服务,而生产ECS的/etc/resolv.conf里配置的DNS服务器是公网的(114.114.114.114),不是华为云内网的DNS(100.125.1.250)。这台ECS是早期从别的平台迁移过来的,当时没注意DNS配置。测试ECS用的是新镜像,自动配了正确的内网DNS。
找到原因就好办了,修改/etc/resolv.conf,把nameserver改成华为云内网DNS地址,然后systemctl restart network。再nslookup一看,解析到内网IP了。再连数据库,毫秒级响应,超时问题瞬间消失。
事后复盘,这种问题其实很隐蔽。大多数时候我们都用内网IP直接连数据库,但这次RDS因为主备切换重建过,我们拿了新的域名来连,正好撞上了DNS解析的坑。如果一开始就用IP,根本不会出现这个故障。
后来我把这个经验写成了团队内部的运维 checklist,每次新购ECS第一件事就是检查DNS配置。另外也建议使用RDS时优先用内网IP而不是域名,除非你有自动切换IP的需求。如果非要用域名,一定要确保ECS的DNS指向正确的内网DNS服务器,避免流量绕道公网。
这次排查让我对云上网络链路有了更深的理解,也提醒自己云产品虽然方便,但底层网络细节依然需要关注。特别是混合架构或者历史遗留系统上云时,很容易忽略这些基础配置。现在生产环境我已经加了监控,定时检测RDS连接耗时,一旦超过阈值就告警,提前发现问题。这次虽然折腾了一整夜,但好歹在上线前爆出来了,要是上线后用户反馈,那就真的被动了。
- 点赞
- 收藏
- 关注作者
评论(0)