Spring Boot应用通过FDNS切换主数据库无需重启的实现方案咨询
Spring Boot应用通过FDNS切换主数据库无需重启的实现方案咨询
兄弟,我太懂你这种头疼的情况了——明明FDNS已经切到新主库B了,应用却死咬着A不放,非得重启才行,之前配的testOnBorrow和validationQuery还没效果,这其实是JVM DNS缓存+数据库连接池策略的双重坑,咱们一步步解决:
先搞懂为啥之前的配置没生效
你用的testOnBorrow和validationQuery没起作用,大概率是两个核心原因:
- JVM默认会把DNS解析结果缓存很久,就算FDNS切了,JVM还是拿着旧的A库IP,新建连接也不会去查新的FDNS
- 连接池里的旧连接没被及时回收,一直占着坑,就算验证配置开了,也没触发新连接的创建
针对性的解决方案,分两步走
第一步:给JVM的DNS缓存“减时效”
Java的DNS缓存是JVM层面的,咱们得强制它定期重新解析FDNS,有两种实用方式:
- 启动参数配置:在Spring Boot应用的启动命令里加这两个参数,直接生效
解释下:-Dnetworkaddress.cache.ttl=60 -Dnetworkaddress.cache.negative.ttl=10cache.ttl=60表示DNS解析结果缓存60秒,到点就自动重新查询;cache.negative.ttl=10表示解析失败的结果只缓存10秒,避免切换时的解析失败被长时间缓存 - 代码动态设置:如果没法改启动参数,也可以在应用初始化阶段加这段代码(比如在带有
@PostConstruct注解的方法里)@PostConstruct public void initDnsCacheConfig() { System.setProperty("networkaddress.cache.ttl", "60"); System.setProperty("networkaddress.cache.negative.ttl", "10"); }
第二步:把连接池的配置拉满,让旧连接“自动下岗”
Spring Boot默认用HikariCP,我先讲这个最常用的,如果你用的是Tomcat JDBC Pool也给你补全配置:
针对HikariCP(默认连接池)
在application.properties/application.yml里补充这些配置:
# 核心:借用连接时必须验证,验证失败直接丢弃旧连接建新的 spring.datasource.hikari.test-on-borrow=true # 验证用的SQL,根据你的数据库调整(比如Oracle用SELECT 1 FROM DUAL) spring.datasource.hikari.connection-test-query=SELECT 1 # 验证超时时间,别太长,3秒足够 spring.datasource.hikari.validation-timeout=3000 # 连接最大生命周期,必须比数据库的wait_timeout短,比如设5分钟,到点自动回收旧连接建新的 spring.datasource.hikari.max-lifetime=300000 # 连接空闲超时,空闲超过10分钟就回收,避免旧连接占坑 spring.datasource.hikari.idle-timeout=600000
针对Tomcat JDBC Pool
如果你的项目用的是Tomcat连接池,配置改成这些:
spring.datasource.tomcat.test-on-borrow=true spring.datasource.tomcat.validation-query=SELECT 1 spring.datasource.tomcat.validation-interval=3000 # 自动回收废弃连接,超时60秒就强制回收 spring.datasource.tomcat.remove-abandoned=true spring.datasource.tomcat.remove-abandoned-timeout=60 # 连接最大存活时间,同样要比数据库的wait_timeout短 spring.datasource.tomcat.max-age=300000
最后验证下效果
配置完后,你手动把FDNS切到B库,然后给应用发几个业务请求,触发连接池借用连接的逻辑——这时候连接池会发现旧连接连的A库失效(或者验证不通过),就会丢弃旧连接,新建连接时JVM已经重新解析了FDNS,自然就连到B库了,完全不用重启应用。
备注:内容来源于stack exchange,提问作者RVD
相关产品推荐
相关产品推荐

