SpringBoot 2.0 Redis配置错误启动不报错

问题

spring-boot 1.5.4升级到spring-boot2.0.6后,部署服务到环境,如果redis host或者port配置错误,会导致服务一直是unhealthy状态,查看服务日志没有错误信息,访问管理端口/actuator/health,只返回{"status":"DOWN"},给排查错误带来很大工作量。

原因

在spring-boot 1.5.4版本,redis client使用的是Jedis直连的方式,是阻塞式的,假如redis host配置错误,健康检查会报出警告如下:

2019-07-25 11:24:55.471  WARN 3130 --- [-10.211.108.214] o.s.b.a.health.RedisHealthIndicator      : Health check failed

org.springframework.data.redis.RedisConnectionFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
......

具体实现在spring-boot-actuator包中的AbstractHealthIndicator

@Override
    public final Health health() {
        Health.Builder builder = new Health.Builder();
        try {
            //尝试连接redis
            doHealthCheck(builder);
        }
        catch (Exception ex) {
            //log warn
            this.logger.warn("Health check failed", ex);
            builder.down(ex);
        }
        return builder.build();
    }

但spring-boot 2.0.6 redis client默认使用的是Lettuce。

Lettuce是一种可伸缩,线程安全,完全非阻塞的Redis客户端,多个线程可以共享一个RedisConnection,它利用Netty NIO 框架来高效地管理多个连接,从而提供了异步和同步数据访问方式,用于构建非阻塞的反应性应用程序。

关于Lettuce和Jedis对比,可以参考这篇文章

由于使用的是Lettuce,健康检查使用的是reactive health check,具体实现在spring-boot-actuator的AbstractReactiveHealthIndicator

@Override
    public final Mono health() {
        try {
            return doHealthCheck(new Health.Builder()).onErrorResume(this::handleFailure);
        }
        catch (Exception ex) {
            return handleFailure(ex);
        }
    }

注意这里catch exception后没有log warn报出错误日志,导致如果redis配置错误,服务虽然不健康,但日志信息里也没有对应错误信息,这是spring-boot2.0的一个bug,会在spring-boot2.1版本中修复。bug对应的issue。

解决方案

配置health端口显示详细信息

虽然2.0版本无法从日志中获取到redis连接失败的日志信息,但可以如下配置让/health端口显示详细信息:

management.endpoint.health.show-details=always

然后访问 管理端口/actuator/health,即可查看服务down的详细原因了。

更换Jedis客户端

如果服务不是reactive响应式应用,可以更换回Jedis配置。阻塞式Jedis的健康检查可以抛出异常信息。

你可能感兴趣的:(SpringBoot 2.0 Redis配置错误启动不报错)