在我们的应用程序中,我们使用HikariCP和Postgres。应用程序通过CNAME连接到数据库(数据库位于CNAME后面)。
将CNAME的值更改为其他数据库(在我们的情况下,副本提升为主数据库)不会反映在我们的连接池中。查询仍尝试从旧数据库中获取数据。仅当maxLifeTime
结束或我们重新启动应用程序时,HikariCP才会进行更改。
maxLifeTime
设置为30分钟,idleTimeout
设置为10分钟(这是HikariCP的默认值)。
问题:HikariCP是否有办法找出连接丢失并从传递的serverName
重新创建新连接,而不等到maxLifeTime
到期?
我尝试了什么:我让maxLifeTime
为2分钟。在最坏的情况下,我的应用程序将关闭2分钟,直到建立新的连接。但是让它2分钟我们指示HikariCP每2分钟建立一个新连接。这是一个好方法吗?我看到人们建议在15-20分钟之间给出一个值,或者比DB连接maxLifeTime
少一些值。
P.S。该应用程序使用clojure-1.7,HikariCP-1.7,postgres-9.6
编辑:澄清为什么我将数据库置于CNAME后面是为了创建一个类似于具有多AZ环境的AWS RDS的设置,如果主数据库用于备份,则另一个数据库开始提供请求。
答案 0 :(得分:2)
你的回答在这里...... Setting the JVM TTL for DNS Name Lookups。
简而言之,如果JVM长时间缓存DNS查找,HikariCP就无法做到。您需要在JVM级别解决此问题。此外,上游DNS服务器的TTL也会产生重大影响 - 也会在本机DNS TTL过期之前进行缓存。
编辑:对不起,我错过了问题的关键部分。正如Taylor所说,你可以暂停池(你需要启用allowPoolSuspension
),软驱逐连接,然后恢复池。在飞行中的连接"在驱逐时将正常完成,然后在他们返回游泳池时立即被驱逐。
答案 1 :(得分:1)
HikariCP有没有办法找出连接是否丢失,需要从传递的serverName重新创建新连接,而不等到maxLifeTime到期时到期?
当您更改CNAME时,之前命名的DB(及其连接)仍然存在,对吧?我假设DNS更改时连接不是丢失; CNAME只指向不同的DB副本/实例。 HikariCP没有检查DNS记录是否已经改变,它只关心连接是否有效。
以下是一个想法:您可以在计划轮询中使用其他线程来进行CNAME更改,并在发生更改时在池中调用softEvictConnections()
。这将立即关闭任何空闲/可预留的连接并标记任何其他连接以进行驱逐。
或者,如果您手动更改CNAME,我认为您可以手动戳您的应用来执行此操作,而不是从内部进行轮询。
如果您想在发生这种情况时停止数据库访问,也可以suspendPool()
和resumePool()
。