diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisMode.java new file mode 100644 index 000000000..ce5610428 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisMode.java @@ -0,0 +1,27 @@ +package com.yomahub.liteflow.parser.redis.mode; + +/** + * 用于定义Redis模式的枚举类 + * + * single单点模式, sentinel哨兵模式 + * 不支持集群模式配置 + * + * @author hxinyu + * @since 2.11.0 + */ +public enum RedisMode { + + SINGLE("single"), + + SENTINEL("sentinel"); + + private String mode; + + RedisMode(String mode) { + this.mode = mode; + } + + public String getMode() { + return mode; + } +} diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java index 356e86a5d..eb60d2cdd 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java @@ -10,6 +10,7 @@ import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLoggerManager; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import org.redisson.config.Config; +import org.redisson.config.SentinelServersConfig; import java.util.List; @@ -24,7 +25,9 @@ public interface RedisParserHelper { LFLog LOG = LFLoggerManager.getLogger(RedisParserHelper.class); - String REDIS_URL_PATTERN = "redis://{}:{}"; + String SINGLE_REDIS_URL_PATTERN = "redis://{}:{}"; + + String SENTINEL_REDIS_URL_PATTERN = "redis://{}"; String CHAIN_XML_PATTERN = "{}"; @@ -42,16 +45,23 @@ public interface RedisParserHelper { /** - * 获取Redisson客户端的Config配置通用方法 + * 获取Redisson客户端的Config配置通用方法(单点模式) * @param redisParserVO redisParserVO - * @param dataBase redisson连接的数据库号 + * @param dataBase redis连接的数据库号 * @return redisson config */ - default Config getRedissonConfig(RedisParserVO redisParserVO, Integer dataBase) { + default Config getSingleRedissonConfig(RedisParserVO redisParserVO, Integer dataBase) { Config config = new Config(); - String redisAddress = StrFormatter.format(REDIS_URL_PATTERN, redisParserVO.getHost(), redisParserVO.getPort()); + String redisAddress = StrFormatter.format(SINGLE_REDIS_URL_PATTERN, redisParserVO.getHost(), redisParserVO.getPort()); + //如果配置了用户名和密码 + if (StrUtil.isNotBlank(redisParserVO.getUsername()) && StrUtil.isNotBlank(redisParserVO.getPassword())) { + config.useSingleServer().setAddress(redisAddress) + .setUsername(redisParserVO.getUsername()) + .setPassword(redisParserVO.getPassword()) + .setDatabase(dataBase); + } //如果配置了密码 - if (StrUtil.isNotBlank(redisParserVO.getPassword())) { + else if (StrUtil.isNotBlank(redisParserVO.getPassword())) { config.useSingleServer().setAddress(redisAddress) .setPassword(redisParserVO.getPassword()) .setDatabase(dataBase); @@ -64,6 +74,37 @@ public interface RedisParserHelper { return config; } + /** + * 获取Redisson客户端的Config配置通用方法(哨兵模式) + * @param redisParserVO redisParserVO + * @param dataBase redis连接的数据库号 + * @return redisson Config + */ + default Config getSentinelRedissonConfig(RedisParserVO redisParserVO, Integer dataBase) { + Config config = new Config(); + SentinelServersConfig sentinelConfig = config.useSentinelServers() + .setMasterName(redisParserVO.getMasterName()); + redisParserVO.getSentinelAddress().forEach(address -> { + sentinelConfig.addSentinelAddress(StrFormatter.format(SENTINEL_REDIS_URL_PATTERN, address)); + }); + //如果配置了用户名和密码 + if(StrUtil.isNotBlank(redisParserVO.getUsername()) && StrUtil.isNotBlank(redisParserVO.getPassword())) { + sentinelConfig.setUsername(redisParserVO.getUsername()) + .setPassword(redisParserVO.getPassword()) + .setDatabase(dataBase); + } + //如果配置了密码 + else if(StrUtil.isNotBlank(redisParserVO.getPassword())) { + sentinelConfig.setPassword(redisParserVO.getPassword()) + .setDatabase(dataBase); + } + //没有配置密码 + else { + sentinelConfig.setDatabase(dataBase); + } + return config; + } + /** * script节点的修改/添加 * diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserMode.java index 13c4b8753..258229c61 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserMode.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserMode.java @@ -1,8 +1,9 @@ package com.yomahub.liteflow.parser.redis.mode; /** - * 用于定义redis规则存储和监听方式的枚举类 + * 用于定义Redis规则存储和监听方式的枚举类 * + * poll轮询拉取模式, sub监听模式 * @author hxinyu * @since 2.11.0 */ diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java index ae4d2ee38..b9c3b2ea7 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java @@ -8,6 +8,7 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.digest.DigestUtil; import com.yomahub.liteflow.parser.redis.exception.RedisException; import com.yomahub.liteflow.parser.redis.mode.RClient; +import com.yomahub.liteflow.parser.redis.mode.RedisMode; import com.yomahub.liteflow.parser.redis.mode.RedisParserHelper; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import com.yomahub.liteflow.spi.holder.ContextAwareHolder; @@ -75,12 +76,28 @@ public class RedisParserPollingMode implements RedisParserHelper { catch (Exception ignored) { } if (ObjectUtil.isNull(chainClient)) { - Config config = getRedissonConfig(redisParserVO, redisParserVO.getChainDataBase()); - this.chainClient = new RClient(Redisson.create(config)); - //如果有脚本数据 - if (ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { - config = getRedissonConfig(redisParserVO, redisParserVO.getScriptDataBase()); - this.scriptClient = new RClient(Redisson.create(config)); + RedisMode redisMode = redisParserVO.getRedisMode(); + Config config; + //Redis单点模式 + if (redisMode.equals(RedisMode.SINGLE)){ + config = getSingleRedissonConfig(redisParserVO, redisParserVO.getChainDataBase()); + this.chainClient = new RClient(Redisson.create(config)); + //如果有脚本数据 + if (ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { + config = getSingleRedissonConfig(redisParserVO, redisParserVO.getScriptDataBase()); + this.scriptClient = new RClient(Redisson.create(config)); + } + } + + //Redis哨兵模式 + else if (redisMode.equals(RedisMode.SENTINEL)) { + config = getSentinelRedissonConfig(redisParserVO, redisParserVO.getChainDataBase()); + this.chainClient = new RClient(Redisson.create(config)); + //如果有脚本数据 + if (ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { + config = getSentinelRedissonConfig(redisParserVO, redisParserVO.getScriptDataBase()); + this.scriptClient = new RClient(Redisson.create(config)); + } } } //创建定时任务线程池 diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java index 67c9697f2..b115baec5 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java @@ -8,6 +8,7 @@ import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.parser.redis.exception.RedisException; import com.yomahub.liteflow.parser.redis.mode.RClient; +import com.yomahub.liteflow.parser.redis.mode.RedisMode; import com.yomahub.liteflow.parser.redis.mode.RedisParserHelper; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import com.yomahub.liteflow.spi.holder.ContextAwareHolder; @@ -48,12 +49,28 @@ public class RedisParserSubscribeMode implements RedisParserHelper { catch (Exception ignored) { } if (ObjectUtil.isNull(chainClient)) { - Config config = getRedissonConfig(redisParserVO, redisParserVO.getChainDataBase()); - this.chainClient = new RClient(Redisson.create(config)); - //如果有脚本数据 - if (ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { - config = getRedissonConfig(redisParserVO, redisParserVO.getScriptDataBase()); - this.scriptClient = new RClient(Redisson.create(config)); + RedisMode redisMode = redisParserVO.getRedisMode(); + Config config; + //Redis单点模式 + if (redisMode.equals(RedisMode.SINGLE)){ + config = getSingleRedissonConfig(redisParserVO, redisParserVO.getChainDataBase()); + this.chainClient = new RClient(Redisson.create(config)); + //如果有脚本数据 + if (ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { + config = getSingleRedissonConfig(redisParserVO, redisParserVO.getScriptDataBase()); + this.scriptClient = new RClient(Redisson.create(config)); + } + } + + //Redis哨兵模式 + else if (redisMode.equals(RedisMode.SENTINEL)) { + config = getSentinelRedissonConfig(redisParserVO, redisParserVO.getChainDataBase()); + this.chainClient = new RClient(Redisson.create(config)); + //如果有脚本数据 + if (ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { + config = getSentinelRedissonConfig(redisParserVO, redisParserVO.getScriptDataBase()); + this.scriptClient = new RClient(Redisson.create(config)); + } } } } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java index 9ec2026f8..7aeaecd70 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java @@ -1,9 +1,12 @@ package com.yomahub.liteflow.parser.redis.vo; +import com.yomahub.liteflow.parser.redis.mode.RedisMode; import com.yomahub.liteflow.parser.redis.mode.RedisParserMode; +import java.util.List; + /** - * 用于解析RuleSourceExtData的vo类,用于Redis模式中 + * 用于解析RuleSourceExtData的vo类, 用于Redis模式中 * * @author hxinyu * @since 2.11.0 @@ -11,12 +14,24 @@ import com.yomahub.liteflow.parser.redis.mode.RedisParserMode; public class RedisParserVO { - /*连接地址*/ + /*Redis配置模式 单点/哨兵, 默认为单点模式*/ + private RedisMode redisMode = RedisMode.SINGLE; + + /*单点模式 连接地址*/ private String host; - /*端口号*/ + /*单点模式 端口号*/ private Integer port; + /*哨兵模式 主节点名*/ + private String masterName; + + /*哨兵模式 哨兵节点连接地址 ip:port, 可配置多个*/ + private List sentinelAddress; + + /*用户名 需要Redis 6.0及以上*/ + private String username; + /*密码*/ private String password; @@ -41,6 +56,21 @@ public class RedisParserVO { /*脚本配置的键名 若没有脚本数据可不配置*/ private String scriptKey; + public void setRedisMode(String redisMode) { + redisMode = redisMode.toUpperCase(); + try{ + RedisMode m = RedisMode.valueOf(redisMode); + this.redisMode = m; + } + catch (Exception ignored) { + //转换出错默认为单点模式 + } + } + + public RedisMode getRedisMode() { + return redisMode; + } + public String getHost() { return host; } @@ -57,6 +87,30 @@ public class RedisParserVO { this.port = port; } + public String getMasterName() { + return masterName; + } + + public void setMasterName(String masterName) { + this.masterName = masterName; + } + + public List getSentinelAddress() { + return sentinelAddress; + } + + public void setSentinelAddress(List sentinelAddress) { + this.sentinelAddress = sentinelAddress; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + public String getPassword() { return password; } @@ -127,4 +181,24 @@ public class RedisParserVO { public void setScriptKey(String scriptKey) { this.scriptKey = scriptKey; } + + @Override + public String toString() { + return "RedisParserVO{" + + "redisMode=" + redisMode + + ", host='" + host + '\'' + + ", port=" + port + + ", masterName=" + masterName + + ", sentinelAddress=" + sentinelAddress + + ", username='" + username + '\'' + + ", password='" + password + '\'' + + ", mode=" + mode + + ", pollingInterval=" + pollingInterval + + ", pollingStartTime=" + pollingStartTime + + ", chainDataBase=" + chainDataBase + + ", chainKey='" + chainKey + '\'' + + ", scriptDataBase=" + scriptDataBase + + ", scriptKey='" + scriptKey + '\'' + + '}'; + } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisSubscribeTestCondition.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisSubscribeTestCondition.java deleted file mode 100644 index 724e8df75..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisSubscribeTestCondition.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.yomahub.liteflow.test.redis; - -import cn.hutool.core.util.StrUtil; -import org.redisson.Redisson; -import org.redisson.api.RedissonClient; -import org.redisson.api.redisnode.RedisNodes; -import org.redisson.api.redisnode.RedisSingle; -import org.redisson.config.Config; - -import java.util.concurrent.TimeUnit; - -/** - * 判断本地6379端口是否启动了Redis - */ -public class RedisSubscribeTestCondition { - - /** - * @return true为本地未启动Redis - */ - public static boolean notStartRedis() { - try{ - Config config = new Config(); - config.useSingleServer().setAddress("redis://127.0.0.1:6379"); - RedissonClient redissonClient = Redisson.create(config); - RedisSingle redisNode = redissonClient.getRedisNodes(RedisNodes.SINGLE); - return !redisNode.pingAll(15000, TimeUnit.MICROSECONDS); - } catch (Exception e) { - return true; - } - } -}