Browse Source

Redis cluster configuration support

pull/2113/head
ShvaykaD 7 years ago
committed by Andrew Shvayka
parent
commit
38d7c1e826
  1. 35
      application/src/main/resources/thingsboard.yml
  2. 65
      dao/src/main/java/org/thingsboard/server/dao/cache/TBRedisCacheConfiguration.java
  3. 77
      dao/src/main/java/org/thingsboard/server/dao/cache/TBRedisClusterConfiguration.java
  4. 88
      dao/src/main/java/org/thingsboard/server/dao/cache/TBRedisStandaloneConfiguration.java

35
application/src/main/resources/thingsboard.yml

@ -278,10 +278,41 @@ redis:
# standalone or cluster
connection:
type: standalone
standalone:
host: "${REDIS_HOST:localhost}"
port: "${REDIS_PORT:6379}"
db: "${REDIS_DB:0}"
password: "${REDIS_PASSWORD:}"
useDefaultClientConfig: "${REDIS_USE_DEFAULT_CLIENT_CONFIG:true}"
# this value may be used only if you used not default ClientConfig
clientName: "${REDIS_CLIENT_NAME:standalone}"
# this value may be used only if you used not default ClientConfig
connectTimeout: "${REDIS_CLIENT_CONNECT_TIMEOUT:30000}"
# this value may be used only if you used not default ClientConfig
readTimeout: "${REDIS_CLIENT_READ_TIMEOUT:60000}"
# this value may be used only if you used not default ClientConfig
usePoolConfig: "${REDIS_CLIENT_USE_POOL_CONFIG:false}"
cluster:
# Comma-separated list of "host:port" pairs to bootstrap from.
nodes: "${REDIS_NODES:}"
# Maximum number of redirects to follow when executing commands across the cluster.
max-redirects: "${REDIS_MAX_REDIRECTS:12}"
useDefaultPoolConfig: "${REDIS_USE_DEFAULT_POOL_CONFIG:true}"
# db index
db: "${REDIS_DB:0}"
# db password
password: "${REDIS_PASSWORD:}"
# pool config
pool_config:
maxTotal: "${REDIS_POOL_CONFIG_MAX_TOTAL:128}"
maxIdle: "${REDIS_POOL_CONFIG_MAX_IDLE:128}"
minIdle: "${REDIS_POOL_CONFIG_MIN_IDLE:16}"
testOnBorrow: "${REDIS_POOL_CONFIG_TEST_ON_BORROW:true}"
testOnReturn: "${REDIS_POOL_CONFIG_TEST_ON_RETURN:true}"
testWhileIdle: "${REDIS_POOL_CONFIG_TEST_WHILE_IDLE:true}"
minEvictableMs: "${REDIS_POOL_CONFIG_MIN_EVICTABLE_MS:60000}"
evictionRunsMs: "${REDIS_POOL_CONFIG_EVICTION_RUNS_MS:30000}"
maxWaitMills: "${REDIS_POOL_CONFIG_MAX_WAIT_MS:60000}"
numberTestsPerEvictionRun: "${REDIS_POOL_CONFIG_NUMBER_TESTS_PER_EVICTION_RUN:3}"
blockWhenExhausted: "${REDIS_POOL_CONFIG_BLOCK_WHEN_EXHAUSTED:true}"
# Check new version updates parameters
updates:

65
dao/src/main/java/org/thingsboard/server/dao/cache/TBRedisCacheConfiguration.java

@ -31,35 +31,54 @@ import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.util.Assert;
import org.thingsboard.server.common.data.id.EntityId;
import redis.clients.jedis.JedisPoolConfig;
@Configuration
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis", matchIfMissing = false)
@EnableCaching
@Data
public class TBRedisCacheConfiguration {
public abstract class TBRedisCacheConfiguration {
@Value("${redis.connection.host}")
private String host;
@Value("${redis.pool_config.maxTotal}")
private int maxTotal;
@Value("${redis.connection.port}")
private Integer port;
@Value("${redis.pool_config.maxIdle}")
private int maxIdle;
@Value("${redis.connection.db}")
private Integer db;
@Value("${redis.pool_config.minIdle}")
private int minIdle;
@Value("${redis.connection.password}")
private String password;
@Value("${redis.pool_config.testOnBorrow}")
private boolean testOnBorrow;
@Value("${redis.pool_config.testOnReturn}")
private boolean testOnReturn;
@Value("${redis.pool_config.testWhileIdle}")
private boolean testWhileIdle;
@Value("${redis.pool_config.minEvictableMs}")
private long minEvictableMs;
@Value("${redis.pool_config.evictionRunsMs}")
private long evictionRunsMs;
@Value("${redis.pool_config.maxWaitMills}")
private long maxWaitMills;
@Value("${redis.pool_config.numberTestsPerEvictionRun}")
private int numberTestsPerEvictionRun;
@Value("${redis.pool_config.blockWhenExhausted}")
private boolean blockWhenExhausted;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
JedisConnectionFactory factory = new JedisConnectionFactory();
factory.setHostName(host);
factory.setPort(port);
factory.setDatabase(db);
factory.setPassword(password);
return factory;
return loadFactory();
}
protected abstract JedisConnectionFactory loadFactory();
@Bean
public CacheManager cacheManager(RedisConnectionFactory cf) {
DefaultFormattingConversionService redisConversionService = new DefaultFormattingConversionService();
@ -78,4 +97,20 @@ public class TBRedisCacheConfiguration {
Assert.notNull(registry, "ConverterRegistry must not be null!");
registry.addConverter(EntityId.class, String.class, EntityId::toString);
}
protected JedisPoolConfig buildPoolConfig() {
final JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(maxTotal);
poolConfig.setMaxIdle(maxIdle);
poolConfig.setMinIdle(minIdle);
poolConfig.setTestOnBorrow(testOnBorrow);
poolConfig.setTestOnReturn(testOnReturn);
poolConfig.setTestWhileIdle(testWhileIdle);
poolConfig.setMinEvictableIdleTimeMillis(minEvictableMs);
poolConfig.setTimeBetweenEvictionRunsMillis(evictionRunsMs);
poolConfig.setMaxWaitMillis(maxWaitMills);
poolConfig.setNumTestsPerEvictionRun(numberTestsPerEvictionRun);
poolConfig.setBlockWhenExhausted(blockWhenExhausted);
return poolConfig;
}
}

77
dao/src/main/java/org/thingsboard/server/dao/cache/TBRedisClusterConfiguration.java

@ -0,0 +1,77 @@
/**
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.cache;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Configuration
@ConditionalOnMissingBean(CaffeineCacheConfiguration.class)
@ConditionalOnProperty(prefix = "redis.connection", value = "type", havingValue = "cluster")
public class TBRedisClusterConfiguration extends TBRedisCacheConfiguration {
private static final String COMMA = ",";
private static final String COLON = ":";
@Value("${redis.cluster.nodes}")
private String clusterNodes;
@Value("${redis.cluster.max-redirects}")
private Integer maxRedirects;
@Value("${redis.cluster.useDefaultPoolConfig}")
private boolean useDefaultPoolConfig;
@Value("${redis.password}")
private String password;
public JedisConnectionFactory loadFactory() {
RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration();
clusterConfiguration.setClusterNodes(getNodes(clusterNodes));
clusterConfiguration.setMaxRedirects(maxRedirects);
clusterConfiguration.setPassword(password);
if (useDefaultPoolConfig) {
return new JedisConnectionFactory(clusterConfiguration);
} else {
return new JedisConnectionFactory(clusterConfiguration, buildPoolConfig());
}
}
private List<RedisNode> getNodes(String nodes) {
List<RedisNode> result;
if (StringUtils.isBlank(nodes)) {
result = Collections.emptyList();
} else {
result = new ArrayList<>();
for (String hostPort : nodes.split(COMMA)) {
String host = hostPort.split(COLON)[0];
Integer port = Integer.valueOf(hostPort.split(COLON)[1]);
result.add(new RedisNode(host, port));
}
}
return result;
}
}

88
dao/src/main/java/org/thingsboard/server/dao/cache/TBRedisStandaloneConfiguration.java

@ -0,0 +1,88 @@
/**
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.cache;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import java.time.Duration;
@Configuration
@ConditionalOnMissingBean(CaffeineCacheConfiguration.class)
@ConditionalOnProperty(prefix = "redis.connection", value = "type", havingValue = "standalone")
public class TBRedisStandaloneConfiguration extends TBRedisCacheConfiguration {
@Value("${redis.standalone.host}")
private String host;
@Value("${redis.standalone.port}")
private Integer port;
@Value("${redis.standalone.clientName}")
private String clientName;
@Value("${redis.standalone.connectTimeout}")
private Long connectTimeout;
@Value("${redis.standalone.readTimeout}")
private Long readTimeout;
@Value("${redis.standalone.useDefaultClientConfig}")
private boolean useDefaultClientConfig;
@Value("${redis.standalone.usePoolConfig}")
private boolean usePoolConfig;
@Value("${redis.db}")
private Integer db;
@Value("${redis.password}")
private String password;
public JedisConnectionFactory loadFactory() {
RedisStandaloneConfiguration standaloneConfiguration = new RedisStandaloneConfiguration();
standaloneConfiguration.setHostName(host);
standaloneConfiguration.setPort(port);
standaloneConfiguration.setDatabase(db);
standaloneConfiguration.setPassword(password);
if (useDefaultClientConfig) {
return new JedisConnectionFactory(standaloneConfiguration);
} else {
return new JedisConnectionFactory(standaloneConfiguration, buildClientConfig());
}
}
private JedisClientConfiguration buildClientConfig() {
if (usePoolConfig) {
return JedisClientConfiguration.builder()
.clientName(clientName)
.connectTimeout(Duration.ofMillis(connectTimeout))
.readTimeout(Duration.ofMillis(readTimeout))
.usePooling().poolConfig(buildPoolConfig())
.build();
} else {
return JedisClientConfiguration.builder()
.clientName(clientName)
.connectTimeout(Duration.ofMillis(connectTimeout))
.readTimeout(Duration.ofMillis(readTimeout)).build();
}
}
}
Loading…
Cancel
Save