如何避免Amazon Aurora Writer实例切换导致Node.js应用无法写入数据
故障原因
你遇到的问题是Aurora Writer故障切换后,Node.js mysql连接池持有的存量长连接仍然指向已降级为Reader的旧Writer实例,导致写入请求被拒绝。集群端点的DNS切换只会影响新建立的连接,对已经建立的存量长连接不生效。
解决方案
配置连接池连接生命周期,避免长连接永久存活
给连接池添加连接闲置超时和最长存活时间配置,强制过期连接自动销毁重建,保证故障切换后最多在配置的超时时间内就能拿到指向新Writer的连接。参考配置如下:const mysql = require('mysql'); const pool = mysql.createPool({ host: 'sample.cluster-sample.us-west-2.rds.amazonaws.com', user: '你的数据库账号', password: '你的数据库密码', database: '你的数据库名', connectionLimit: 10, // 连接闲置超过5分钟自动销毁 idleTimeoutMillis: 300000, // 连接最长存活时间30分钟,无论是否闲置到期自动销毁 maxConnectionAgeMillis: 1800000 });如果你使用的原版
mysql包不支持连接最长存活时间配置,可以手动定时销毁旧连接池再重建,或切换到兼容性更高的mysql2包。禁用不必要的DNS缓存,匹配Aurora集群端点TTL
Aurora集群端点的默认DNS TTL为5秒,不要让操作系统或应用层将DNS解析结果缓存过长时间。可以在连接配置中自定义DNS解析逻辑,每次新建连接时强制获取最新的解析结果,避免DNS缓存导致新连接仍然指向旧Writer实例。添加写入错误重试和连接销毁逻辑
当写入请求返回只读实例错误(错误码ER_OPTION_PREVENTS_STATEMENT)或连接异常时,立即销毁当前报错的连接,再触发请求重试。新的请求会触发连接池新建连接,此时解析集群端点DNS即可拿到新Writer的IP,恢复写入能力。写入前校验实例角色(可选,适合高可用要求高的场景)
每次从连接池获取连接用于写入前,先执行SHOW VARIABLES LIKE 'read_only'校验,如果返回值为ON,说明当前连接指向只读实例,立即销毁该连接重新获取,避免无效写入请求。
内容的提问来源于stack exchange,提问作者Ken Yip

