当前位置: 首页 > news >正文

一次由IDEA配置引发的Redis连接问题

偶然的发现

书接上回 『谁动了我的SunEC?——记深夜排查SSL握手失败的惊魂一小时』,某日下午,A同学又找到我确认个接口的实现逻辑,说话间点击了IDEA的启动按钮开始启动服务。

项目启动过程中我猛然发现A同学IDEA的控制台怎么出现了错误,瞬间引起了我的注意

我:“嗯? 你这怎么启动还报错, 啥配置不对吗 ? “

A同学:”我这最近一直是这样,不过不影响使用,接口啥的都能正常访问。“

我:“具体啥错误,你没分析看看 ?”

A同学:”是一个Redis连接的错误,好像是Redis连接不上。"

我想了想:“嘶,我们现在没有使用Redis了才对呀,两级缓存那个Redis配置我都关掉了,怎么还会去连接Redis。我本地启动也没报错呀。”

我:“先说你的接口问题吧,这个等接口讨论完再看下“

此处省略接口逻辑的讨论过程

问题排查

我说:“现在再看下刚才那个Redis连不上的问题”

A同学说:“就是很奇怪,我看配置啥也没问题,但是不知道为啥启动就会去尝试连接Redis,之前我也尝试改了些配置,打断点看了下,没找到问题”

我说:“我看看”,随后坐到A同学工位上。看了下启动错误,如下(完整错误太长,此处保留关键的部分)

2025-03-10 16:38:33.190 [] [boundedElastic-1] WARN  org.springframework.boot.actuate.redis.RedisReactiveHealthIndicator - Redis health check failed
org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis; nested exception is org.springframework.data.redis.connection.PoolException: Could not get a resource from the pool; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to localhost:6379
	at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.translateException(LettuceConnectionFactory.java:1689) ~[spring-data-redis-2.7.18.jar:2.7.18]
	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Assembly trace from producer [reactor.core.publisher.MonoSubscribeOnCallable] :
	reactor.core.publisher.Mono.subscribeOn(Mono.java:4589)
	org.springframework.boot.actuate.redis.RedisReactiveHealthIndicator.getConnection(RedisReactiveHealthIndicator.java:57)
Error has been observed at the following site(s):
	*__Mono.subscribeOn ⇢ at org.springframework.boot.actuate.redis.RedisReactiveHealthIndicator.getConnection(RedisReactiveHealthIndicator.java:57)
	|_     Mono.flatMap ⇢ at org.springframework.boot.actuate.redis.RedisReactiveHealthIndicator.doHealthCheck(RedisReactiveHealthIndicator.java:52)

核心信息就是 “Redis health check failed”

再往前看日志输出的位置,发现是来自org.springframework.boot.actuate.redis.RedisReactiveHealthIndicator这个类,这不是spring-boot-actuator中的类么。

我说:“这应该是spring-boot-actuator进行组件健康检查了,是不是你的配置文件开启了这个配置。”

说话间,我打开A同学工程里的application.yaml文件,发现配置都是禁用的,尝试进行了一些配置的调整验证发现并没有效果。

这就有意思了,配置没开启,但是却执行了,版本啥的不一致导致的 ?

目测一番没发现问题,那就只能顺着异常栈去分析了,看看出错的位置在哪里,也就是这行

RedisReactiveHealthIndicator.doHealthCheck(RedisReactiveHealthIndicator.java:52),然后再往下分析,哪里调用了这个方法,也就是异常栈里面最底下的那个Caused by, 结果如下

Caused by: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: localhost/127.0.0.1:6379

Caused by: java.net.ConnectException: Connection refused: no further information
	at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method) ~[?:?]
	at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:777) ~[?:?]
	at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:337) ~[netty-transport-4.1.101.Final.jar:4.1.101.Final]
	at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:334) ~[netty-transport-4.1.101.Final.jar:4.1.101.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:776) ~[netty-transport-4.1.101.Final.jar:4.1.101.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724) ~[netty-transport-4.1.101.Final.jar:4.1.101.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650) ~[netty-transport-4.1.101.Final.jar:4.1.101.Final]
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) ~[netty-transport-4.1.101.Final.jar:4.1.101.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[netty-common-4.1.101.Final.jar:4.1.101.Final]
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.101.Final.jar:4.1.101.Final]
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.101.Final.jar:4.1.101.Final]
	at java.lang.Thread.run(Thread.java:829) ~[?:?]

这怎么还是一个线程直接拉起来的,这下完了,从哪起的这个线程,异常栈里是看不见的,触发调用这个健康检查的代码位置也没找到。

这时候A同学轻声道:“其实就是启动报个错,也不影响啥”。

这不是我的风格,必须干掉它。

深入分析

既然堆栈上没有直接线索,那就剩下分析源码了,于是我从 RedisReactiveHealthIndicator 中输出的Redis health check failed 这行日志作为切入点,再结合 RedisReactiveHealthIndicator.doHealthCheck(RedisReactiveHealthIndicator.java:52)找到了如下代码

在这里插入图片描述

那么,可以确定的就是这行代码被执行了,那么剩下就是往回找,找到调用这个方法的最外层入口就行了。

经过一通分析和DEBUG,最终串联了这些类

在这里插入图片描述

稍有眉目

最后定位到,项目启动了JMX监控(如上图所示的类),执行了组件的健康检查,但是程序里并没有启动相关服务,这个是从哪启动的。

难道是加了什么JVM启动参数 ?立即查询启动的VM参数发现并没有配置相关内容,那还有可能是哪里加的呢 ?

突然,想到IDEA启动项目时,会在控制台输出所有的JVM参数,看一下就知道了,随即查看IDEA控制台输出的java启动命令,果然,在里面发现了可疑配置参数

-Dcom.sun.management.jmxremote 
-Dspring.jmx.enabled=true 
-Dspring.liveBeansView.mbeanDomain 
-Dspring.application.admin.enabled=true 
"-Dmanagement.endpoints.jmx.exposure.include=*"

但是,我们并没有添加这些参数,这是从哪里来的 ? IDEA自己加的么

然后,我在自己电脑上启动了下同样查看了控制台参数,发现并没有输出相关配置

然后看了下A同学的IDEA版本,2024 标准版本,而我的是2022.2.3社区版

难道是IDEA标准版自己加了这些参数 ?

发现问题

然后查看IDEA Edit Configurations 检查相关配置,最终发现了如下配置,这个配置默认是没勾选了,也就是会增加一系列JMX的参数,最终导致启动时候加载到了 actuator 中的 JMX模块的代码,从而触发了Redis的健康检查代码。

在这里插入图片描述

随后,勾选 Disable JMX endpoints 启动项目,一切正常。

相关文章:

  • 区块链赋能:用Python开发去中心化投票系统
  • 清晰易懂的Node.js安装教程
  • 五种方案实现双链路可靠数据传输
  • IntelliJ IDEA 调试技巧指南
  • LLM系列笔记之微调数据集格式
  • 网络编程---创建客户端和服务端以及协议包
  • 开源免费一句话生成儿童故事视频核心思想解析
  • Java基础语法练习42(基本绘图-基本的事件处理机制-小坦克的绘制-键盘控制坦克移动)
  • leetcode-47.全排列II
  • 深度学习之防止过拟合
  • 【华三】路由器交换机忘记登入密码或super密码的重启操作
  • 打乱一维数组中的元素,并按照4个一组的方式添加到二维数组中
  • Python基础入门掌握(十五)
  • 删除 Git 历史提交记录中的大文件
  • 大数据学习(71)-三范式构成
  • pycharm-python國際象棋遊戲代碼
  • 【程序人生】成功人生架构图(分层模型)
  • 前端面试:ajax 和 xhr 是什么关系?
  • 内网攻防——红日靶场(一)
  • 织梦dedecms管理员密码重置工具下载
  • 制定出台民营经济促进法有何重大意义?全国人大常委会法工委回应
  • 科学家为AI模型设置“防火墙”,以防止被不法分子滥用
  • 商务部新闻发言人就波音公司飞回拟交付飞机答记者问
  • 普京发表声明感谢协助俄军收复库尔斯克州的朝鲜军人
  • 四川在浙江公开招募200名退休教师,赴川支教帮扶
  • 王文涛会见德国汽车工业协会主席穆勒