redisson-spring-boot-starter 的自动配置是通过以下属性实现的 spring.redis.redisson.config=classpath:redisson.yaml 而通常springcloud是通过远程拉取的方式,上述的配置方式需要在本地按环境配置多套,又背弃了configserver的初衷。希望官方能符合spring的规范提供api,让spring框架使用者更容易接入redisson
[redisson]redisson-spring-boot-starter 对spring cloud config 支持不友好
回答
自己定义就行啊,比如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));
}
我的意思是redisson.yml需要存储在本地。还需要分环境存xx-dev,xx-test.这个对于配置中心这种不太友好。我必须把我的账号密码存储在项目中
哦,明白你的意思了,确实,用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));
}
嗯嗯,所以我觉得既然是redisson-spring-boot-starter,那为什么不更靠近spring的标准呢
我目前还是Spring boot-data-starter-data-redis的链接方式,就是配置spring.redis.cluster.nodes
这种。也想转到redisson上,但是也有需要根据不同环境配置不同yaml文件的疑问
redisson-spring-boot-starter的意义是支持SpringBoot,Spring Cloud Config Server的配置方式目前还没有正式支持。
Redisson提供的是一套工具,它可以在不依赖其他框架的情况下独立使用。同时在这套工具的基础上,根据不同的框架提供相关的支持,但不会受限于其中。采用外部配置文件的方式允许在不修改代码的情况下,在测试,整合和生产等持续交付的环节中适应不同的Redis环境。这样的设计,允许各个开发人员有不同配置的Redis测试环境,同时还能有效地与生产环境隔离开。通常情况下开发人员的配置文件无需提交代码仓库里,避免了泄漏密码等安全问题。
在配置文件中新增加的变量解析功能或许对这个问题有帮助。 https://github.com/redisson/redisson/issues/2086#issuecomment-488672200
以singleServerConfig为例,按如下流程:
- 把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
- 新建如下类结构:
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中读取,可以从配置中心拉取,避开了必须配置文件路径的问题,从而实现兼容远程配置的问题。
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