diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/util/AssertUtil.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/util/AssertUtil.java new file mode 100644 index 00000000..46dcc11e --- /dev/null +++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/util/AssertUtil.java @@ -0,0 +1,48 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * 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 com.alibaba.csp.sentinel.util; + +/** + * Util class for checking arguments. + */ +public class AssertUtil { + + private AssertUtil(){} + + public static void notEmpty(String string, String message) { + if (StringUtil.isEmpty(string)) { + throw new IllegalArgumentException(message); + } + } + + public static void notNull(Object object, String message) { + if (object == null) { + throw new IllegalArgumentException(message); + } + } + + public static void isTrue(boolean value, String message) { + if (!value) { + throw new IllegalArgumentException(message); + } + } + + public static void assertState(boolean condition, String message) { + if (!condition) { + throw new IllegalStateException(message); + } + } +} diff --git a/sentinel-demo/README.md b/sentinel-demo/README.md index 4ddf454b..810ac7ab 100755 --- a/sentinel-demo/README.md +++ b/sentinel-demo/README.md @@ -6,4 +6,4 @@ The examples demonstrate: - How to use various data source extensions of Sentinel (e.g. file, Nacos, ZooKeeper) - How to use Dubbo with Sentinel - How to use Apache RocketMQ client with Sentinel - +- How to use Sentinel annotation support diff --git a/sentinel-extension/sentinel-datasource-redis/README.md b/sentinel-extension/sentinel-datasource-redis/README.md index 8265ab57..399057be 100644 --- a/sentinel-extension/sentinel-datasource-redis/README.md +++ b/sentinel-extension/sentinel-datasource-redis/README.md @@ -1,10 +1,12 @@ # Sentinel DataSource Redis -Sentinel DataSource Redis provides integration with Redis. make Redis -as dynamic rule data source of Sentinel. The data source uses push model (listener) with redis pub/sub feature. +Sentinel DataSource Redis provides integration with Redis. The data source leverages Redis pub-sub feature to implement push model (listener). -**NOTE**: -we not support redis cluster as a pub/sub dataSource now. +The data source uses [Lettuce](https://lettuce.io/) as the Redis client internal. Requires JDK 1.8 or later. + +> **NOTE**: Currently we do not support Redis Cluster now. + +## Usage To use Sentinel DataSource Redis, you should add the following dependency: @@ -25,39 +27,41 @@ ReadableDataSource> redisDataSource = new RedisDataSource FlowRuleManager.register2Property(redisDataSource.getProperty()); ``` -_**redisConnectionConfig**_ : use `RedisConnectionConfig` class to build your connection config. - -_**ruleKey**_ : when the json rule data publish. it also should save to the key for init read. - -_**channel**_ : the channel to listen. - -you can also create multi data source listen for different rule type. - -you can see test cases for usage. - -## Before start +- `redisConnectionConfig`: use `RedisConnectionConfig` class to build your Redis connection config +- `ruleKey`: the rule persistence key of a Redis String +- `channel`: the channel to subscribe -RedisDataSource init config by read from redis key `ruleKey`, value store the latest rule config data. -so you should first config your redis ruleData in back end. +You can also create multi data sources to subscribe for different rule type. -since update redis rule data. it should simultaneously send data to `channel`. -you may implement like this (using Redis transaction): +Note that the data source first loads initial rules from a Redis String (provided `ruleKey`) during initialization. +So for consistency, users should publish the value and save the value to the `ruleKey` simultaneously like this (using Redis transaction): ``` - MULTI -PUBLISH channel value SET ruleKey value +PUBLISH channel value EXEC +``` -``` +An example using Lettuce Redis client: +```java +public void pushRules(List rules, Converter, String> encoder) { + StatefulRedisPubSubConnection connection = client.connectPubSub(); + RedisPubSubCommands subCommands = connection.sync(); + String value = encoder.convert(rules); + subCommands.multi(); + subCommands.set(ruleKey, value); + subCommands.publish(ruleChannel, value); + subCommands.exec(); +} +``` ## How to build RedisConnectionConfig -### Build with redis standLone mode +### Build with Redis standalone mode ```java RedisConnectionConfig config = RedisConnectionConfig.builder() @@ -70,7 +74,7 @@ RedisConnectionConfig config = RedisConnectionConfig.builder() ``` -### Build with redis sentinel mode +### Build with Redis Sentinel mode ```java RedisConnectionConfig config = RedisConnectionConfig.builder() diff --git a/sentinel-extension/sentinel-datasource-redis/pom.xml b/sentinel-extension/sentinel-datasource-redis/pom.xml index b6e0b7e1..04f435f6 100644 --- a/sentinel-extension/sentinel-datasource-redis/pom.xml +++ b/sentinel-extension/sentinel-datasource-redis/pom.xml @@ -13,20 +13,24 @@ jar + 1.8 + 1.8 5.0.1.RELEASE 0.1.6 + + com.alibaba.csp + sentinel-datasource-extension + + io.lettuce lettuce-core ${lettuce.version} - - com.alibaba.csp - sentinel-datasource-extension - + junit junit diff --git a/sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/RedisDataSource.java b/sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/RedisDataSource.java index 678f6c6c..aa5a38a5 100644 --- a/sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/RedisDataSource.java +++ b/sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/RedisDataSource.java @@ -19,9 +19,10 @@ package com.alibaba.csp.sentinel.datasource.redis; import com.alibaba.csp.sentinel.datasource.AbstractDataSource; import com.alibaba.csp.sentinel.datasource.Converter; import com.alibaba.csp.sentinel.datasource.redis.config.RedisConnectionConfig; -import com.alibaba.csp.sentinel.datasource.redis.util.AssertUtil; +import com.alibaba.csp.sentinel.util.AssertUtil; import com.alibaba.csp.sentinel.log.RecordLog; import com.alibaba.csp.sentinel.util.StringUtil; + import io.lettuce.core.RedisClient; import io.lettuce.core.RedisURI; import io.lettuce.core.api.sync.RedisCommands; @@ -29,38 +30,51 @@ import io.lettuce.core.pubsub.RedisPubSubAdapter; import io.lettuce.core.pubsub.StatefulRedisPubSubConnection; import io.lettuce.core.pubsub.api.sync.RedisPubSubCommands; +import java.time.Duration; import java.util.concurrent.TimeUnit; /** + *

* A read-only {@code DataSource} with Redis backend. + *

*

- * When data source init,reads form redis with string k-v,value is string format rule config data. - * This data source subscribe from specific channel and then data published in redis with this channel,data source - * will be notified and then update rule config in time. + * The data source first loads initial rules from a Redis String during initialization. + * Then the data source subscribe from specific channel. When new rules is published to the channel, + * the data source will observe the change in realtime and update to memory. + *

+ *

+ * Note that for consistency, users should publish the value and save the value to the ruleKey simultaneously + * like this (using Redis transaction): + *

+ *  MULTI
+ *  SET ruleKey value
+ *  PUBLISH channel value
+ *  EXEC
+ * 
*

* * @author tiger */ - public class RedisDataSource extends AbstractDataSource { - private RedisClient redisClient = null; + private final RedisClient redisClient; - private String ruleKey; + private final String ruleKey; /** - * Constructor of {@code RedisDataSource} + * Constructor of {@code RedisDataSource}. * - * @param connectionConfig redis connection config. - * @param ruleKey data save in redis. - * @param channel subscribe from channel. - * @param parser convert ruleKey`s value to {@literal alibaba/Sentinel} rule type + * @param connectionConfig Redis connection config + * @param ruleKey data key in Redis + * @param channel channel to subscribe in Redis + * @param parser customized data parser, cannot be empty */ - public RedisDataSource(RedisConnectionConfig connectionConfig, String ruleKey, String channel, Converter parser) { + public RedisDataSource(RedisConnectionConfig connectionConfig, String ruleKey, String channel, + Converter parser) { super(parser); - AssertUtil.notNull(connectionConfig, "redis connection config can not be null"); - AssertUtil.notEmpty(ruleKey, "redis subscribe ruleKey can not be empty"); - AssertUtil.notEmpty(channel, "redis subscribe channel can not be empty"); + AssertUtil.notNull(connectionConfig, "Redis connection config can not be null"); + AssertUtil.notEmpty(ruleKey, "Redis ruleKey can not be empty"); + AssertUtil.notEmpty(channel, "Redis subscribe channel can not be empty"); this.redisClient = getRedisClient(connectionConfig); this.ruleKey = ruleKey; loadInitialConfig(); @@ -68,28 +82,28 @@ public class RedisDataSource extends AbstractDataSource { } /** - * build redis client form {@code RedisConnectionConfig} with io.lettuce. + * Build Redis client fromm {@code RedisConnectionConfig}. * * @return a new {@link RedisClient} */ private RedisClient getRedisClient(RedisConnectionConfig connectionConfig) { if (connectionConfig.getRedisSentinels().size() == 0) { - RecordLog.info("start standLone mode to connect to redis"); - return getRedisStandLoneClient(connectionConfig); + RecordLog.info("[RedisDataSource] Creating stand-alone mode Redis client"); + return getRedisStandaloneClient(connectionConfig); } else { - RecordLog.info("start redis sentinel mode to connect to redis"); + RecordLog.info("[RedisDataSource] Creating Redis Sentinel mode Redis client"); return getRedisSentinelClient(connectionConfig); } } - private RedisClient getRedisStandLoneClient(RedisConnectionConfig connectionConfig) { + private RedisClient getRedisStandaloneClient(RedisConnectionConfig connectionConfig) { char[] password = connectionConfig.getPassword(); String clientName = connectionConfig.getClientName(); RedisURI.Builder redisUriBuilder = RedisURI.builder(); redisUriBuilder.withHost(connectionConfig.getHost()) - .withPort(connectionConfig.getPort()) - .withDatabase(connectionConfig.getDatabase()) - .withTimeout(connectionConfig.getTimeout(), TimeUnit.MILLISECONDS); + .withPort(connectionConfig.getPort()) + .withDatabase(connectionConfig.getDatabase()) + .withTimeout(Duration.ofMillis(connectionConfig.getTimeout())); if (password != null) { redisUriBuilder.withPassword(connectionConfig.getPassword()); } @@ -113,7 +127,7 @@ public class RedisDataSource extends AbstractDataSource { sentinelRedisUriBuilder.withClientName(clientName); } sentinelRedisUriBuilder.withSentinelMasterId(connectionConfig.getRedisSentinelMasterId()) - .withTimeout(connectionConfig.getTimeout(), TimeUnit.MILLISECONDS); + .withTimeout(connectionConfig.getTimeout(), TimeUnit.MILLISECONDS); return RedisClient.create(sentinelRedisUriBuilder.build()); } @@ -138,16 +152,16 @@ public class RedisDataSource extends AbstractDataSource { } @Override - public String readSource() throws Exception { + public String readSource() { if (this.redisClient == null) { - throw new IllegalStateException("redis client has not been initialized or error occurred"); + throw new IllegalStateException("Redis client has not been initialized or error occurred"); } RedisCommands stringRedisCommands = redisClient.connect().sync(); return stringRedisCommands.get(ruleKey); } @Override - public void close() throws Exception { + public void close() { redisClient.shutdown(); } @@ -158,9 +172,8 @@ public class RedisDataSource extends AbstractDataSource { @Override public void message(String channel, String message) { - RecordLog.info(String.format("[RedisDataSource] New property value received for channel %s: %s", channel, message)); + RecordLog.info(String.format("[RedisDataSource] New property value received for channel %s: %s", channel, message)); getProperty().updateValue(parser.convert(message)); } } - } diff --git a/sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/config/RedisConnectionConfig.java b/sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/config/RedisConnectionConfig.java index 6fa23b00..64fa0d7b 100644 --- a/sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/config/RedisConnectionConfig.java +++ b/sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/config/RedisConnectionConfig.java @@ -16,7 +16,7 @@ package com.alibaba.csp.sentinel.datasource.redis.config; -import com.alibaba.csp.sentinel.datasource.redis.util.AssertUtil; +import com.alibaba.csp.sentinel.util.AssertUtil; import com.alibaba.csp.sentinel.util.StringUtil; import java.util.*; @@ -76,7 +76,6 @@ public class RedisConnectionConfig { setTimeout(timeout); } - /** * Returns a new {@link RedisConnectionConfig.Builder} to construct a {@link RedisConnectionConfig}. * @@ -86,7 +85,6 @@ public class RedisConnectionConfig { return new RedisConnectionConfig.Builder(); } - /** * Returns the host. * @@ -240,7 +238,6 @@ public class RedisConnectionConfig { return redisSentinels; } - @Override public String toString() { final StringBuilder sb = new StringBuilder(); @@ -269,7 +266,7 @@ public class RedisConnectionConfig { if (!(o instanceof RedisConnectionConfig)) { return false; } - RedisConnectionConfig redisURI = (RedisConnectionConfig) o; + RedisConnectionConfig redisURI = (RedisConnectionConfig)o; if (port != redisURI.port) { return false; @@ -280,10 +277,12 @@ public class RedisConnectionConfig { if (host != null ? !host.equals(redisURI.host) : redisURI.host != null) { return false; } - if (redisSentinelMasterId != null ? !redisSentinelMasterId.equals(redisURI.redisSentinelMasterId) : redisURI.redisSentinelMasterId != null) { + if (redisSentinelMasterId != null ? !redisSentinelMasterId.equals(redisURI.redisSentinelMasterId) + : redisURI.redisSentinelMasterId != null) { return false; } - return !(redisSentinels != null ? !redisSentinels.equals(redisURI.redisSentinels) : redisURI.redisSentinels != null); + return !(redisSentinels != null ? !redisSentinels.equals(redisURI.redisSentinels) + : redisURI.redisSentinels != null); } @@ -297,7 +296,6 @@ public class RedisConnectionConfig { return result; } - /** * Builder for Redis RedisConnectionConfig. */ @@ -315,7 +313,6 @@ public class RedisConnectionConfig { private Builder() { } - /** * Set Redis host. Creates a new builder. * @@ -435,7 +432,8 @@ public class RedisConnectionConfig { */ public RedisConnectionConfig.Builder withHost(String host) { - AssertUtil.assertState(this.redisSentinels.isEmpty(), "Sentinels are non-empty. Cannot use in Sentinel mode."); + AssertUtil.assertState(this.redisSentinels.isEmpty(), + "Sentinels are non-empty. Cannot use in Sentinel mode."); AssertUtil.notEmpty(host, "Host must not be empty"); this.host = host; @@ -548,7 +546,8 @@ public class RedisConnectionConfig { if (redisSentinels.isEmpty() && StringUtil.isEmpty(host)) { throw new IllegalStateException( - "Cannot build a RedisConnectionConfig. One of the following must be provided Host, Socket or Sentinel"); + "Cannot build a RedisConnectionConfig. One of the following must be provided Host, Socket or " + + "Sentinel"); } RedisConnectionConfig redisURI = new RedisConnectionConfig(); @@ -565,7 +564,8 @@ public class RedisConnectionConfig { redisURI.setRedisSentinelMasterId(redisSentinelMasterId); for (RedisHostAndPort sentinel : redisSentinels) { - redisURI.getRedisSentinels().add(new RedisConnectionConfig(sentinel.getHost(), sentinel.getPort(), timeout)); + redisURI.getRedisSentinels().add( + new RedisConnectionConfig(sentinel.getHost(), sentinel.getPort(), timeout)); } redisURI.setTimeout(timeout); diff --git a/sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/config/RedisHostAndPort.java b/sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/config/RedisHostAndPort.java index 4a199c18..6d8fb20e 100644 --- a/sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/config/RedisHostAndPort.java +++ b/sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/config/RedisHostAndPort.java @@ -16,7 +16,7 @@ package com.alibaba.csp.sentinel.datasource.redis.config; -import com.alibaba.csp.sentinel.datasource.redis.util.AssertUtil; +import com.alibaba.csp.sentinel.util.AssertUtil; /** * An immutable representation of a host and port. @@ -85,7 +85,7 @@ public class RedisHostAndPort { if (!(o instanceof RedisHostAndPort)) { return false; } - RedisHostAndPort that = (RedisHostAndPort) o; + RedisHostAndPort that = (RedisHostAndPort)o; return port == that.port && (host != null ? host.equals(that.host) : that.host == null); } diff --git a/sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/util/AssertUtil.java b/sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/util/AssertUtil.java deleted file mode 100644 index 38e9d470..00000000 --- a/sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/util/AssertUtil.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * 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 com.alibaba.csp.sentinel.datasource.redis.util; - -import com.alibaba.csp.sentinel.util.StringUtil; - -/** - * A util class for filed check - * - * @author tiger - */ -public class AssertUtil { - - private AssertUtil(){} - /** - * Assert that a string is not empty, it must not be {@code null} and it must not be empty. - * - * @param string the object to check - * @param message the exception message to use if the assertion fails - * @throws IllegalArgumentException if the object is {@code null} or the underlying string is empty - */ - public static void notEmpty(String string, String message) { - if (StringUtil.isEmpty(string)) { - throw new IllegalArgumentException(message); - } - } - - /** - * Assert that an object is not {@code null} . - * - * @param object the object to check - * @param message the exception message to use if the assertion fails - * @throws IllegalArgumentException if the object is {@code null} - */ - public static void notNull(Object object, String message) { - if (object == null) { - throw new IllegalArgumentException(message); - } - } - - /** - * Assert that {@code value} is {@literal true}. - * - * @param value the value to check - * @param message the exception message to use if the assertion fails - * @throws IllegalArgumentException if the object array contains a {@code null} element - */ - public static void isTrue(boolean value, String message) { - if (!value) { - throw new IllegalArgumentException(message); - } - } - - /** - * Ensures the truth of an expression involving the state of the calling instance, but not involving any parameters to the - * calling method. - * - * @param condition a boolean expression - * @param message the exception message to use if the assertion fails - * @throws IllegalStateException if {@code expression} is false - */ - public static void assertState(boolean condition, String message) { - if (!condition) { - throw new IllegalStateException(message); - } - } -} diff --git a/sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/RedisConnectionConfigTest.java b/sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/RedisConnectionConfigTest.java index 89850f8e..15a95762 100644 --- a/sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/RedisConnectionConfigTest.java +++ b/sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/RedisConnectionConfigTest.java @@ -17,10 +17,10 @@ package com.alibaba.csp.sentinel.datasource.redis; import com.alibaba.csp.sentinel.datasource.redis.config.RedisConnectionConfig; + import org.junit.Assert; import org.junit.Test; - /** * Test cases for {@link RedisConnectionConfig}. * @@ -42,8 +42,8 @@ public class RedisConnectionConfigTest { String host = "localhost"; String clientName = "clientName"; RedisConnectionConfig redisConnectionConfig = RedisConnectionConfig.Builder.redis(host) - .withClientName("clientName") - .build(); + .withClientName("clientName") + .build(); Assert.assertEquals(redisConnectionConfig.getClientName(), clientName); } @@ -52,8 +52,8 @@ public class RedisConnectionConfigTest { String host = "localhost"; long timeout = 70 * 1000; RedisConnectionConfig redisConnectionConfig = RedisConnectionConfig.Builder.redis(host) - .withTimeout(timeout) - .build(); + .withTimeout(timeout) + .build(); Assert.assertEquals(redisConnectionConfig.getTimeout(), timeout); } @@ -61,11 +61,12 @@ public class RedisConnectionConfigTest { public void testRedisSentinelDefaultPortSuccess() { String host = "localhost"; RedisConnectionConfig redisConnectionConfig = RedisConnectionConfig.Builder.redisSentinel(host) - .withPassword("211233") - .build(); - Assert.assertEquals(null, redisConnectionConfig.getHost()); + .withPassword("211233") + .build(); + Assert.assertNull(redisConnectionConfig.getHost()); Assert.assertEquals(1, redisConnectionConfig.getRedisSentinels().size()); - Assert.assertEquals(RedisConnectionConfig.DEFAULT_SENTINEL_PORT, redisConnectionConfig.getRedisSentinels().get(0).getPort()); + Assert.assertEquals(RedisConnectionConfig.DEFAULT_SENTINEL_PORT, + redisConnectionConfig.getRedisSentinels().get(0).getPort()); } @Test @@ -74,9 +75,9 @@ public class RedisConnectionConfigTest { String host2 = "server2"; int port2 = 1879; RedisConnectionConfig redisConnectionConfig = RedisConnectionConfig.Builder.redisSentinel(host) - .withRedisSentinel(host2, port2) - .build(); - Assert.assertEquals(null, redisConnectionConfig.getHost()); + .withRedisSentinel(host2, port2) + .build(); + Assert.assertNull(redisConnectionConfig.getHost()); Assert.assertEquals(2, redisConnectionConfig.getRedisSentinels().size()); } @@ -86,12 +87,11 @@ public class RedisConnectionConfigTest { String host2 = "server2"; int port2 = 1879; RedisConnectionConfig redisConnectionConfig = RedisConnectionConfig.Builder.redisSentinel(host) - .withRedisSentinel(host2, port2) - .withRedisSentinel(host2, port2) - .withPassword("211233") - .build(); - Assert.assertEquals(null, redisConnectionConfig.getHost()); + .withRedisSentinel(host2, port2) + .withRedisSentinel(host2, port2) + .withPassword("211233") + .build(); + Assert.assertNull(redisConnectionConfig.getHost()); Assert.assertEquals(3, redisConnectionConfig.getRedisSentinels().size()); } - } diff --git a/sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/SentinelModeRedisDataSourceTest.java b/sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/SentinelModeRedisDataSourceTest.java index c291940d..054e7dc3 100644 --- a/sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/SentinelModeRedisDataSourceTest.java +++ b/sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/SentinelModeRedisDataSourceTest.java @@ -23,6 +23,7 @@ import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; + import io.lettuce.core.RedisClient; import io.lettuce.core.RedisURI; import io.lettuce.core.api.sync.RedisCommands; @@ -36,39 +37,43 @@ import java.util.Random; * * @author tiger */ -@Ignore(value = "before run this test. you should build your own redisSentinel config in local") +@Ignore(value = "Before run this test, you need to set up your Redis Sentinel.") public class SentinelModeRedisDataSourceTest { private String host = "localhost"; private int redisSentinelPort = 5000; - private String redisSentinelMasterId = "mymaster"; - - private String ruleKey = "redis.redisSentinel.flow.rulekey"; + private String redisSentinelMasterId = "myMaster"; - private String channel = "redis.redisSentinel.flow.channel"; + private String ruleKey = "sentinel.rules.flow.ruleKey"; + private String channel = "sentinel.rules.flow.channel"; private final RedisClient client = RedisClient.create(RedisURI.Builder.sentinel(host, redisSentinelPort) - .withSentinelMasterId(redisSentinelMasterId).build()); + .withSentinelMasterId(redisSentinelMasterId).build()); @Before public void initData() { Converter> flowConfigParser = buildFlowConfigParser(); RedisConnectionConfig config = RedisConnectionConfig.builder() - .withRedisSentinel(host, redisSentinelPort) - .withRedisSentinel(host, redisSentinelPort) - .withSentinelMasterId(redisSentinelMasterId).build(); + .withRedisSentinel(host, redisSentinelPort) + .withRedisSentinel(host, redisSentinelPort) + .withSentinelMasterId(redisSentinelMasterId).build(); initRedisRuleData(); - ReadableDataSource> redisDataSource = new RedisDataSource>(config, ruleKey, channel, flowConfigParser); + ReadableDataSource> redisDataSource = new RedisDataSource<>(config, + ruleKey, channel, flowConfigParser); FlowRuleManager.register2Property(redisDataSource.getProperty()); } @Test public void testConnectToSentinelAndPubMsgSuccess() { int maxQueueingTimeMs = new Random().nextInt(); - String flowRulesJson = "[{\"resource\":\"test\", \"limitApp\":\"default\", \"grade\":1, \"count\":\"0.0\", \"strategy\":0, \"refResource\":null, " + - "\"controlBehavior\":0, \"warmUpPeriodSec\":10, \"maxQueueingTimeMs\":" + maxQueueingTimeMs + ", \"controller\":null}]"; + String flowRulesJson = + "[{\"resource\":\"test\", \"limitApp\":\"default\", \"grade\":1, \"count\":\"0.0\", \"strategy\":0, " + + "\"refResource\":null, " + + + "\"controlBehavior\":0, \"warmUpPeriodSec\":10, \"maxQueueingTimeMs\":" + maxQueueingTimeMs + + ", \"controller\":null}]"; RedisCommands subCommands = client.connect().sync(); subCommands.multi(); subCommands.set(ruleKey, flowRulesJson); @@ -97,20 +102,17 @@ public class SentinelModeRedisDataSourceTest { } private Converter> buildFlowConfigParser() { - return new Converter>() { - @Override - public List convert(String source) { - return JSON.parseObject(source, new TypeReference>() { - }); - } - }; + return source -> JSON.parseObject(source, new TypeReference>() {}); } private void initRedisRuleData() { - String flowRulesJson = "[{\"resource\":\"test\", \"limitApp\":\"default\", \"grade\":1, \"count\":\"0.0\", \"strategy\":0, \"refResource\":null, " + + String flowRulesJson = + "[{\"resource\":\"test\", \"limitApp\":\"default\", \"grade\":1, \"count\":\"0.0\", \"strategy\":0, " + + "\"refResource\":null, " + + "\"controlBehavior\":0, \"warmUpPeriodSec\":10, \"maxQueueingTimeMs\":500, \"controller\":null}]"; RedisCommands stringRedisCommands = client.connect().sync(); String ok = stringRedisCommands.set(ruleKey, flowRulesJson); - Assert.assertTrue(ok.equals("OK")); + Assert.assertEquals("OK", ok); } } diff --git a/sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/StandLoneRedisDataSourceTest.java b/sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/StandaloneRedisDataSourceTest.java similarity index 80% rename from sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/StandLoneRedisDataSourceTest.java rename to sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/StandaloneRedisDataSourceTest.java index bc6c6935..408d0bc4 100644 --- a/sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/StandLoneRedisDataSourceTest.java +++ b/sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/StandaloneRedisDataSourceTest.java @@ -17,6 +17,7 @@ package com.alibaba.csp.sentinel.datasource.redis; import ai.grakn.redismock.RedisServer; + import com.alibaba.csp.sentinel.datasource.Converter; import com.alibaba.csp.sentinel.datasource.ReadableDataSource; import com.alibaba.csp.sentinel.datasource.redis.config.RedisConnectionConfig; @@ -24,6 +25,7 @@ import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; + import io.lettuce.core.RedisClient; import io.lettuce.core.RedisURI; import io.lettuce.core.api.sync.RedisCommands; @@ -39,24 +41,23 @@ import java.util.List; import java.util.Random; /** - * Redis standLone mode test cases for {@link RedisDataSource}. + * Redis stand-alone mode test cases for {@link RedisDataSource}. * * @author tiger */ -public class StandLoneRedisDataSourceTest { +public class StandaloneRedisDataSourceTest { private static RedisServer server = null; private RedisClient client; - private String ruleKey = "redisSentinel.flow.rulekey"; - - private String channel = "redisSentinel.flow.channel"; + private String ruleKey = "sentinel.rules.flow.ruleKey"; + private String channel = "sentinel.rules.flow.channel"; @Before public void buildResource() { try { - //bind to a random port + // Bind to a random port. server = RedisServer.newRedisServer(); server.start(); } catch (IOException e) { @@ -65,11 +66,12 @@ public class StandLoneRedisDataSourceTest { Converter> flowConfigParser = buildFlowConfigParser(); client = RedisClient.create(RedisURI.create(server.getHost(), server.getBindPort())); RedisConnectionConfig config = RedisConnectionConfig.builder() - .withHost(server.getHost()) - .withPort(server.getBindPort()) - .build(); + .withHost(server.getHost()) + .withPort(server.getBindPort()) + .build(); initRedisRuleData(); - ReadableDataSource> redisDataSource = new RedisDataSource>(config, ruleKey, channel, flowConfigParser); + ReadableDataSource> redisDataSource = new RedisDataSource>(config, + ruleKey, channel, flowConfigParser); FlowRuleManager.register2Property(redisDataSource.getProperty()); } @@ -79,8 +81,12 @@ public class StandLoneRedisDataSourceTest { Assert.assertEquals(1, rules.size()); int maxQueueingTimeMs = new Random().nextInt(); StatefulRedisPubSubConnection connection = client.connectPubSub(); - String flowRules = "[{\"resource\":\"test\", \"limitApp\":\"default\", \"grade\":1, \"count\":\"0.0\", \"strategy\":0, \"refResource\":null, " + - "\"controlBehavior\":0, \"warmUpPeriodSec\":10, \"maxQueueingTimeMs\":" + maxQueueingTimeMs + ", \"controller\":null}]"; + String flowRules = + "[{\"resource\":\"test\", \"limitApp\":\"default\", \"grade\":1, \"count\":\"0.0\", \"strategy\":0, " + + "\"refResource\":null, " + + + "\"controlBehavior\":0, \"warmUpPeriodSec\":10, \"maxQueueingTimeMs\":" + maxQueueingTimeMs + + ", \"controller\":null}]"; RedisPubSubCommands subCommands = connection.sync(); subCommands.multi(); subCommands.set(ruleKey, flowRules); @@ -113,7 +119,7 @@ public class StandLoneRedisDataSourceTest { RedisCommands stringRedisCommands = client.connect().sync(); stringRedisCommands.del(ruleKey); String value = stringRedisCommands.get(ruleKey); - Assert.assertEquals(value, null); + Assert.assertNull(value); } @After @@ -126,17 +132,14 @@ public class StandLoneRedisDataSourceTest { } private Converter> buildFlowConfigParser() { - return new Converter>() { - @Override - public List convert(String source) { - return JSON.parseObject(source, new TypeReference>() { - }); - } - }; + return source -> JSON.parseObject(source, new TypeReference>() {}); } private void initRedisRuleData() { - String flowRulesJson = "[{\"resource\":\"test\", \"limitApp\":\"default\", \"grade\":1, \"count\":\"0.0\", \"strategy\":0, \"refResource\":null, " + + String flowRulesJson = + "[{\"resource\":\"test\", \"limitApp\":\"default\", \"grade\":1, \"count\":\"0.0\", \"strategy\":0, " + + "\"refResource\":null, " + + "\"controlBehavior\":0, \"warmUpPeriodSec\":10, \"maxQueueingTimeMs\":500, \"controller\":null}]"; RedisCommands stringRedisCommands = client.connect().sync(); String ok = stringRedisCommands.set(ruleKey, flowRulesJson);