[redisson]redisson-spring-boot-starter 对spring cloud config 支持不友好

2024-07-18 480 views
7

redisson-spring-boot-starter 的自动配置是通过以下属性实现的 spring.redis.redisson.config=classpath:redisson.yaml 而通常springcloud是通过远程拉取的方式,上述的配置方式需要在本地按环境配置多套,又背弃了configserver的初衷。希望官方能符合spring的规范提供api,让spring框架使用者更容易接入redisson

回答

8

自己定义就行啊,比如yaml的时候, redisson.config: | redisson config xxxxxx


    @Value("${redission.config:#{null}}")
    private String redissonConfig;

    @Bean(destroyMethod = "shutdown")
    public RedissonClient redisson() throws IOException {
        Assert.notNull(redissonConfig, "redisson配置无效");
        return Redisson.create(Config.fromYAML(redissonConfig));
    }
6

我的意思是redisson.yml需要存储在本地。还需要分环境存xx-dev,xx-test.这个对于配置中心这种不太友好。我必须把我的账号密码存储在项目中

5

哦,明白你的意思了,确实,用redisson-spring-boot-starter还真不如,在SC config 或者SCA nacos里,自己定义一个redisson的配置文件,然后用我的方式


    @Value("${redission.config:#{null}}")
    private String redissonConfig;

    @Bean(destroyMethod = "shutdown")
    public RedissonClient redisson() throws IOException {
        Assert.notNull(redissonConfig, "redisson配置无效");
        return Redisson.create(Config.fromYAML(redissonConfig));
    }
2

嗯嗯,所以我觉得既然是redisson-spring-boot-starter,那为什么不更靠近spring的标准呢

9

我目前还是Spring boot-data-starter-data-redis的链接方式,就是配置spring.redis.cluster.nodes这种。也想转到redisson上,但是也有需要根据不同环境配置不同yaml文件的疑问

3

redisson-spring-boot-starter的意义是支持SpringBoot,Spring Cloud Config Server的配置方式目前还没有正式支持。

Redisson提供的是一套工具,它可以在不依赖其他框架的情况下独立使用。同时在这套工具的基础上,根据不同的框架提供相关的支持,但不会受限于其中。采用外部配置文件的方式允许在不修改代码的情况下,在测试,整合和生产等持续交付的环节中适应不同的Redis环境。这样的设计,允许各个开发人员有不同配置的Redis测试环境,同时还能有效地与生产环境隔离开。通常情况下开发人员的配置文件无需提交代码仓库里,避免了泄漏密码等安全问题。

7
关于题主的问题,我这有一个解决方案:

以singleServerConfig为例,按如下流程:

  1. 把yaml里的配置,挪到远程的yml配置中:
    //注意这里,把配置放到redisson下
    redisson:
    singleServerConfig:
    idleConnectionTimeout: 10000
    pingTimeout: 1000
    connectTimeout: 10000
    timeout: 3000
    retryAttempts: 3
    retryInterval: 1500
    reconnectionTimeout: 3000
    failedAttempts: 3
    password: xxxx
    subscriptionsPerConnection: 5
    clientName: null
    address: "redis://192.168.1.2:6379"
    subscriptionConnectionMinimumIdleSize: 1
    subscriptionConnectionPoolSize: 50
    connectionMinimumIdleSize: 32
    connectionPoolSize: 64
    database: 0
    dnsMonitoring: false
    dnsMonitoringInterval: 5000
    threads: 0
    nettyThreads: 0
    //注意这里和原配置略有不同
    codec:
    _class: org.redisson.codec.JsonJacksonCodec     
    transportMode: NIO
  2. 新建如下类结构:

Properties.class

@Component
@ConfigurationProperties(prefix = "redisson")
@Data
public class Properties {
    @JsonProperty
    SingleServerConfig singleServerConfig;
    int threads;
    int nettyThreads;
    String transportMode;
    Codec codec;
}

Codec.class

@Data
public class Codec{
    @JsonProperty(value = "class")
    String _class;
}

BaseConfig.class

@Data
public class BaseConfig<T extends org.redisson.config.BaseConfig<T>> {

    private static final Logger log = LoggerFactory.getLogger("config");

    /**
     * If pooled connection not used for a <code>timeout</code> time
     * and current connections amount bigger than minimum idle connections pool size,
     * then it will closed and removed from pool.
     * Value in milliseconds.
     */
    private int idleConnectionTimeout = 10000;

    /**
     * Timeout during connecting to any Redis server.
     * Value in milliseconds.
     */
    private int connectTimeout = 10000;

    /**
     * Redis server response timeout. Starts to countdown when Redis command was succesfully sent.
     * Value in milliseconds.
     */
    private int timeout = 3000;

    private int retryAttempts = 3;

    private int retryInterval = 1500;

    /**
     * Password for Redis authentication. Should be null if not needed
     */
    private String password;

    private String username;

    /**
     * Subscriptions per Redis connection limit
     */
    private int subscriptionsPerConnection = 5;

    /**
     * Name of client connection
     */
    private String clientName;

    private boolean sslEnableEndpointIdentification = true;

    private SslProvider sslProvider = SslProvider.JDK;

    private URL sslTruststore;

    private String sslTruststorePassword;

    private URL sslKeystore;

    private String sslKeystorePassword;

    private int pingConnectionInterval;

    private boolean keepAlive;

    private boolean tcpNoDelay;
}

SingleServerConfig.class

@Data
public class SingleServerConfig extends BaseConfig{
    /**
     * Redis server address
     *
     */
    private String address;

    /**
     * Minimum idle subscription connection amount
     */
    private int subscriptionConnectionMinimumIdleSize = 1;

    /**
     * Redis subscription connection maximum pool size
     *
     */
    private int subscriptionConnectionPoolSize = 50;

    /**
     * Minimum idle Redis connection amount
     */
    private int connectionMinimumIdleSize = 24;

    /**
     * Redis connection maximum pool size
     */
    private int connectionPoolSize = 64;

    /**
     * Database index used for Redis connection
     */
    private int database = 0;

    /**
     * Interval in milliseconds to check DNS
     */
    private long dnsMonitoringInterval = 5000;
}

RedissonConfiguration.class

@Configuration
@ComponentScan
@EnableCaching
public  class RedissonConfiguration {
    @Bean(destroyMethod="shutdown")
    RedissonClient redisson(Properties properties) throws IOException {
        ObjectMapper mapper=new ObjectMapper();
        String jsonString = mapper.writeValueAsString(properties);
        Config config = Config.fromJSON(jsonString);
        RedissonClient redisson = Redisson.create(config);
        return redisson;
    }
}

PS : BaseConfig.class、SingleServerConfig.class以及其他子类的属性,可以直接从源码中同名类复制,比较省事,另:如果你有多套配置的需求,你可以找到相应的配置类,如同建立SingleServerConfig一样建立其他的配置类,多个ServerConfig配置类可以同时存在,不会冲突的

这样,就把配置改为了从yml中读取,可以从配置中心拉取,避开了必须配置文件路径的问题,从而实现兼容远程配置的问题。

3

define RedissonConfig.java

package com.example.config;

import lombok.Data;
import org.redisson.config.*;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "redisson")
@Data
public class RedissonConfig extends Config {

    private Boolean enableRedissonConfig;

    public boolean isEnabled(){
        if(enableRedissonConfig == null){
            return false;
        }
        return enableRedissonConfig;
    }

}

custom RedissonAutoConfiguration.java

package com.example.config;

...
...

/**
 * copy org.redisson.spring.starter.RedissonAutoConfiguration and edit
 */
@Configuration
@EnableConfigurationProperties({RedissonProperties.class, RedisProperties.class})
public class RedissonAutoConfiguration {
    ...
    ...
    @Bean(destroyMethod = "shutdown")
    @ConditionalOnMissingBean(RedissonClient.class)
    public RedissonClient redisson(RedissonConfig redissonConfig) throws IOException {
        Config config = null;

        ...
        ...

        if(redissonConfig != null && redissonConfig.isEnabled()){ //add this
            config = redissonConfig;
        } else if (redissonProperties.getConfig() != null) {
            ...
            ...
        } else if (redisProperties.getSentinel() != null) {
            ...
            ...
        } else if (clusterMethod != null && ReflectionUtils.invokeMethod(clusterMethod, redisProperties) != null) {
            ...
            ...
        } else {
            ...
            ...
        }

        ...
        ...

        return Redisson.create(config);
    }

    private String[] convert(List<String> nodesObject) {
        ...
        ...
    }

    private InputStream getConfigStream() throws IOException {
        ...
        ...
    }

}

add config in your yml file on nacos or consul

spring:
  ...
  ...

redisson:
  enableRedissonConfig: true #enable or disable config below
  clusterServersConfig:
    nodeAddresses:
      - "redis://${REDIS_HOST:127.0.0.1}:6371"
      - "redis://${REDIS_HOST:127.0.0.1}:6372"
      - "redis://${REDIS_HOST:127.0.0.1}:6373"
    password: "foofoo"
  lockWatchdogTimeout: 30000