nacos修改druid配置自动刷新后服务异常

背景:某天Springboot Admin监控告警,detail显示微服务A offline,经排查发现此时服务处于假死状态,推断由于数据库连接池maxThreads配置过小导致高并发场景下服务无法响应外部请求。

解决方案:nacos 公共配置添加

druid 连接池配置

spring.datasource.druid.timeBetweenEvictionRunsMillis=60000

spring.datasource.druid.max-active=100

spring.datasource.druid.initial-size=5

spring.datasource.druid.max-wait=10000

spring.datasource.druid.min-idle=5

配置添加完后,我们重启了被告警的服务,但由于配置改在公共配置上,且公共配置开启了自动刷新功能,接着其他微服务也出现了异常。

排查过程:

1)应急方案:由于配置直接改在了生产环境,为了保障线上的正常响应,我们首先回退该配置,因为此时服务状态已正常,故而暂不进行线程池配置的优化;

2)问题排查:
在这里插入图片描述
以上是部分告警内容(敏感信息已剔除)。

通过告警内容可见,服务异常原因是因为无法正确加载数据源相关配置导致。

接着,我们再去查看服务器日志信息。

在这里插入图片描述
通过服务器日志可见,由于nacos公共配置refresh属性设置为true,因此nacos客户端会基于长连接定时同步服务端配置。接下来我们从NacosContextRefresher源码开始分析。
我们发现NacosContextRefresher对象中registerNacosListener方法,方法如下:

在这里插入图片描述

该方法其实就是基于消息总线机制,创建一个监听器,放入注册服务,如果有刷新了,就会调用innerReceive方法,进行刷新历史的添加和刷新事件的通知,也就是你自己可以接受到这个事件后做点扩展。

接下来我们继续debug nacos源码。
在这里插入图片描述

我们发现断点走过listener之后直接进入了CacheData的异常捕获之中,通过点击异常发现确实是druid连接池报错。

异常信息如下图。

在这里插入图片描述

图片很清晰的表明是由于druid中 initial-size无法设置导致nacos重载失败并抛出异常。

接下来我们查看druid源码,发现该字段初始化方法有对init状态的判断,若init为true,则方法抛出异常,该异常也即nacos CacheData中捕获的异常。

在这里插入图片描述

我们继续查看源码,发现该字段为容器初始化加载组件完成后即设置完成,该字段无法动态修改。

在这里插入图片描述

至此,该异常原因链路完整,出现此异常就是因为druid扩展参数中initial-size该字段不支持动态更新导致。

猜你喜欢

转载自blog.csdn.net/weixin_39195030/article/details/112471641