• SpringBoot项目连接Redis启动报错(Unable to validate object)


    问题

    某新项目(基于SpringBoot)在线上部署完成后启动失败,查看错误日志如下:
    Error creating bean with name 'jedisPool'...
    ...
    Caused by: redis.clients.jedis.exceptions.JedisException: Could not get a resource from the pool
    ...
    Caused by: java.util.NoSuchElementException: Unable to validate object
    ...

    分析&解决

    项目使用了Redis,基于Jedis封装了方便Redis操作的SpringBoot starter,里面在初始化配置时创建了ShardedJedisPool
    项目使用了阿里云的应用配置管理(ACM),其中Redis连接相关参数配置在云上的yml文件中,配置了主机、端口、密码、数据库编号、超时参数等。
    项目在测试环境启动正常,检查线上环境参数配置,通过阿里云的网页客户端连接Redis正常。

    yml文件里Redis部分配置如下:

    redis:
      host: xxx.redis.rds.aliyuncs.com
      port: 6379
      password: xxx
      database: 5
    

    查看创建ShardedJedisPool代码如下:

    String password = redisProperties.getPassword();
    password = !StringUtils.isEmpty(password) ? (":" + password + "@") : "";
    String redisUri = "redis://" + password + host + ":" + port + "/" + database;
    JedisShardInfo shard = new JedisShardInfo(redisUri);
    

    注意到线上环境的Redis密码有特殊字符#,查看new JedisShardInfo,点进去看是通过URI.create(host)来创建URI对象,
    #通过URLEncoder.encode()编码为%23,将redis.password替换后重启项目,启动成功。

    后续

    项目后来引入了redisson框架,使用分布式锁。

    <dependency>
        <groupId>org.redisson</groupId>
        <artifactId>redisson</artifactId>
        <version>3.5.0</version>
    </dependency>
    

    其中redisson配置如下:

    redisson:
      address: redis://${spring.redis.host}:${spring.redis.port}
      password: ${spring.redis.password}
      database: ${spring.redis.database}
    

    构建RedissonClient代码如下:

    @Bean
    @ConditionalOnProperty(
        name = {"redisson.address"}
    )
    RedissonClient redissonSingle() {
        Config config = new Config();
        config.setLockWatchdogTimeout(this.redssionProperties.getLockWatchdogTimeout());
        SingleServerConfig serverConfig = ((SingleServerConfig)config.useSingleServer().setDatabase(this.redssionProperties.getDatabase()).setAddress(this.redssionProperties.getAddress()).setTimeout(this.redssionProperties.getTimeout())).setConnectionPoolSize(this.redssionProperties.getConnectionPoolSize()).setConnectionMinimumIdleSize(this.redssionProperties.getConnectionMinimumIdleSize());
        if (StringUtils.isNotBlank(this.redssionProperties.getPassword())) {
            serverConfig.setPassword(this.redssionProperties.getPassword());
        }
    
        return Redisson.create(config);
    }
    

    项目启动报错,提示密码错误,注意到这里通过SingleServerConfig#setPassword来设置密码,因此不需要使用转换后的密码,直接用原密码即可。
    修改redisson配置如下:

    redisson:
      address: redis://${spring.redis.host}:${spring.redis.port}
      password: xxx
      database: ${spring.redis.database}
    

    重新启动项目成功^_^!

    参考

  • 相关阅读:
    如何实线浏览器title的小图标以及rgb和rgbaopacity的区别
    雪碧图
    定位的使用及页面的布局
    标准文档流及浮动的元素和坏处
    三种列表以及行级块三种元素的转变
    背景的处理
    h5前期js知识点10月19日总结
    h5前期jg知识点总结10月18日
    h5前期js10月17日知识点
    h5前期js知识点10月16日总结
  • 原文地址:https://www.cnblogs.com/cdfive2018/p/16171624.html
Copyright © 2020-2023  润新知