Micronaut应用连接Redis独立集群遇认证及RESP协议版本问题
问题描述
我有一个简单的Micronaut应用,尝试通过以下配置连接Redis独立实例:
application.yml 配置
redis: uri: redis://redis.dev.com port: 6379 username: db_cache password: password io-thread-pool-size: 10 computation-thread-pool-size: 10 cache: expiration-after-write-policy: 1h pool: enabled: true min-idle: 5 max-total: 15 max-idle: 10
版本信息
micronautRedisLettuce = "5.3.2" micronautVersion = "3.8.1"
应用可正常启动,但访问健康检查端点时返回503响应,报错信息如下:
io.micronaut.management.health.indicator.HealthResult - {} - Health indicator [redis(Primary)] reported exception: io.lettuce.core.RedisConnectionException: Unable to connect to dbaasprod-re-sppst-dc-107793.dev.target.com/<unresolved>:6379 io.lettuce.core.RedisConnectionException: Unable to connect to dbaasprod-re-sppst-dc-107793.dev.target.com/<unresolved>:6379 at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:78) ~[lettuce-core-6.2.1.RELEASE.jar:6.2.1.RELEASE] at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:56) ~[lettuce-core-6.2.1.RELEASE.jar:6.2.1.RELEASE] at io.lettuce.core.AbstractRedisClient.getConnection(AbstractRedisClient.java:350) ~[lettuce-core-6.2.1.RELEASE.jar:6.2.1.RELEASE] at io.lettuce.core.RedisClient.connect(RedisClient.java:216) ~[lettuce-core-6.2.1.RELEASE.jar:6.2.1.RELEASE] at io.lettuce.core.RedisClient.connect(RedisClient.java:201) ~[lettuce-core-6.2.1.RELEASE.jar:6.2.1.RELEASE] at io.micronaut.configuration.lettuce.health.RedisHealthIndicator.healthResultForClient(RedisHealthIndicator.java:107) ~[micronaut-redis-lettuce-5.3.2.jar:5.3.2] at io.micronaut.configuration.lettuce.health.RedisHealthIndicator.lambda$getResult$0(RedisHealthIndicator.java:99) ~[micronaut-redis-lettuce-5.3.2.jar:5.3.2] at reactor.core.publisher.FluxFlatMap$FlatMapMain.onNext(FluxFlatMap.java:386) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.FluxIterable$IterableSubscription.slowPath(FluxIterable.java:272) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:230) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.FluxFlatMap$FlatMapMain.onSubscribe(FluxFlatMap.java:371) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:165) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:87) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.Flux.subscribe(Flux.java:8660) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onComplete(FluxConcatArray.java:258) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.FluxConcatArray.subscribe(FluxConcatArray.java:78) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.Flux.subscribe(Flux.java:8660) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.FluxFlatMap$FlatMapMain.onNext(FluxFlatMap.java:426) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.FluxIterable$IterableSubscription.slowPath(FluxIterable.java:272) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:230) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.FluxFlatMap$FlatMapMain.onSubscribe(FluxFlatMap.java:371) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:165) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:87) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.Mono.subscribe(Mono.java:4444) ~[reactor-core-3.5.0.jar:3.5.0] at io.micronaut.management.health.monitor.HealthMonitorTask.monitor(HealthMonitorTask.java:98) ~[micronaut-management-3.8.1.jar:3.8.1] at io.micronaut.management.health.monitor.$HealthMonitorTask$Definition$Exec.dispatch(Unknown Source) ~[micronaut-management-3.8.1.jar:3.8.1] at io.micronaut.context.AbstractExecutableMethodsDefinition$DispatchedExecutableMethod.invoke(AbstractExecutableMethodsDefinition.java:378) ~[micronaut-inject-3.8.1.jar:3.8.1] at io.micronaut.inject.DelegatingExecutableMethod.invoke(DelegatingExecutableMethod.java:76) ~[micronaut-inject-3.8.1.jar:3.8.1] at io.micronaut.scheduling.processor.ScheduledMethodProcessor.lambda$process$5(ScheduledMethodProcessor.java:127) ~[micronaut-context-3.8.1.jar:3.8.1] at io.micrometer.core.instrument.composite.CompositeTimer.record(CompositeTimer.java:141) ~[micrometer-core-1.10.2.jar:1.10.2] at io.micrometer.core.instrument.Timer.lambda$wrap$0(Timer.java:196) ~[micrometer-core-1.10.2.jar:1.10.2] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) ~[?:?] at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305) ~[?:?] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305) ~[?:?] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[?:?] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[?:?] at java.lang.Thread.run(Thread.java:833) ~[?:?] Caused by: io.lettuce.core.RedisCommandExecutionException: NOAUTH HELLO must be called with the client already authenticated, otherwise the HELLO AUTH <user> <pass> option can be used to authenticate the client and select the RESP protocol version at the same time at io.lettuce.core.internal.ExceptionFactory.createExecutionException(ExceptionFactory.java:147) ~[lettuce-core-6.2.1.RELEASE.jar:6.2.1.RELEASE] at io.lettuce.core.internal.ExceptionFactory.createExecutionException(ExceptionFactory.java:116) ~[lettuce-core-6.2.1.RELEASE.jar:6.2.1.RELEASE] at io.lettuce.core.protocol.AsyncCommand.completeResult(AsyncCommand.java:120) ~[lettuce-core-6.2.1.RELEASE.jar:6.2.1.RELEASE] at io.lettuce.core.protocol.AsyncCommand.complete(AsyncCommand.java:111) ~[lettuce-core-6.2.1.RELEASE.jar:6.2.1.RELEASE] at io.lettuce.core.protocol.CommandWrapper.complete(CommandWrapper.java:63) ~[lettuce-core-6.2.1.RELEASE.jar:6.2.1.RELEASE] at io.lettuce.core.protocol.CommandHandler.complete(CommandHandler.java:747) ~[lettuce-core-6.2.1.RELEASE.jar:6.2.1.RELEASE] at io.lettuce.core.protocol.CommandHandler.decode(CommandHandler.java:682) ~[lettuce-core-6.2.1.RELEASE.jar:6.2.1.RELEASE] at io.lettuce.core.protocol.CommandHandler.channelRead(CommandHandler.java:599) ~[lettuce-core-6.2.1.RELEASE.jar:6.2.1.RELEASE]
核心错误提示翻译后:
NOAUTH 错误:必须在客户端已认证的情况下调用HELLO命令,否则可以使用HELLO AUTH <用户名> <密码>选项同时完成客户端认证和选择RESP协议版本
解决方案
这个问题源于Lettuce客户端连接Redis 6+实例时,默认先发送HELLO命令协商RESP版本,但Redis要求必须先完成认证才能执行HELLO命令,或在HELLO命令中直接附带认证信息。可通过以下方式解决:
- 将认证信息嵌入Redis URI
修改application.yml的Redis配置,把用户名和密码直接整合到URI中,Lettuce会自动处理认证与HELLO命令的顺序:
redis: uri: redis://db_cache:password@redis.dev.com:6379 io-thread-pool-size: 10 computation-thread-pool-size: 10 cache: expiration-after-write-policy: 1h pool: enabled: true min-idle: 5 max-total: 15 max-idle: 10
- 配置Lettuce禁用HELLO命令协商
如果无法修改URI格式,可添加配置强制使用RESP2协议,跳过HELLO命令直接用AUTH认证:
redis: uri: redis://redis.dev.com port: 6379 username: db_cache password: password lettuce: protocol-version: RESP2 io-thread-pool-size: 10 computation-thread-pool-size: 10 cache: expiration-after-write-policy: 1h pool: enabled: true min-idle: 5 max-total: 15 max-idle: 10
- 升级Micronaut Redis依赖版本
Micronaut Redis Lettuce的新版本已修复该认证顺序问题,可尝试升级到6.x及以上版本,保持原有配置即可正常连接。
内容的提问来源于stack exchange,提问作者Ryuzaki L
相关产品推荐
相关产品推荐

