一次由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 启动项目,一切正常。

### 配置 IntelliJ IDEA 2024 连接到 Docker 容器中的 Redis 为了使 IntelliJ IDEA 2024 能够成功连接到运行在 Docker 容器内的 Redis 实例,需要遵循一系列配置步骤来确保开发环境与容器化服务之间的无缝通信。 #### 创建并启动 Redis 容器 首先,在本地环境中创建一个简单的 `docker-compose.yml` 文件用于定义和管理多容器应用。对于仅涉及单个 Redis 容器的情况,此文件可以非常简洁: ```yaml version: '3' services: redis: image: "redis:alpine" container_name: my_redis_container ports: - "6379:6379" ``` 上述 YAML 片段指定了使用官方提供的精简版 Redis 映像,并映射主机的 6379 端口至容器内部相同的端口号以便外部访问[^1]。 #### 设置 IDE 插件支持 安装 **Redis** 或者更通用的服务工具插件如 **Database Tools and SQL** 来增强 IntelliJ 对数据库的支持能力。通过这些插件可以直接从界面操作远程或本地的数据存储资源。 - 打开设置对话框 (`Ctrl+Alt+S`) 寻找 Plugins 分类下的 Marketplace 输入 “Redis” 查找合适的扩展程序完成安装。 - 同样在此处也可以找到 Database 工具集,它不仅限于关系型数据库还涵盖了 NoSQL 类型比如 Redis。 #### 添加数据源以接入 Redis 利用刚刚添加的功能模块向项目引入新的数据源: - 在顶部菜单栏依次点击 File -> New -> Data Source -> Redis... - 接下来会弹出窗口提示输入必要的连接详情,这里的关键在于正确填写 Host 和 Port 字段——即前面提到过的宿主机暴露出来的端口地址(默认情况下应为 localhost:6379),其余选项可根据实际需求调整[^2]。 #### 测试连接有效性 最后一步便是验证整个流程是否顺畅无阻。一旦所有前置条件都已满足,则可以在 IDE 内部轻松测试同目标实例间的连通状况;如果一切正常的话,应该能够看到所选键空间内存在的条目列表以及其他相关信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值