Pārlūkot izejas kodu

Improvements for Redis data source and demo

Signed-off-by: Eric Zhao <sczyh16@gmail.com>
master
Eric Zhao pirms 6 gadiem
vecāks
revīzija
b1f33675c5
11 mainītis faili ar 207 papildinājumiem un 214 dzēšanām
  1. +48
    -0
      sentinel-core/src/main/java/com/alibaba/csp/sentinel/util/AssertUtil.java
  2. +1
    -1
      sentinel-demo/README.md
  3. +28
    -24
      sentinel-extension/sentinel-datasource-redis/README.md
  4. +8
    -4
      sentinel-extension/sentinel-datasource-redis/pom.xml
  5. +43
    -30
      sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/RedisDataSource.java
  6. +12
    -12
      sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/config/RedisConnectionConfig.java
  7. +2
    -2
      sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/config/RedisHostAndPort.java
  8. +0
    -81
      sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/util/AssertUtil.java
  9. +18
    -18
      sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/RedisConnectionConfigTest.java
  10. +23
    -21
      sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/SentinelModeRedisDataSourceTest.java
  11. +24
    -21
      sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/StandaloneRedisDataSourceTest.java

+ 48
- 0
sentinel-core/src/main/java/com/alibaba/csp/sentinel/util/AssertUtil.java Parādīt failu

@@ -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);
}
}
}

+ 1
- 1
sentinel-demo/README.md Parādīt failu

@@ -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

+ 28
- 24
sentinel-extension/sentinel-datasource-redis/README.md Parādīt failu

@@ -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<String, List<FlowRule>> 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 <T> void pushRules(List<T> rules, Converter<List<T>, String> encoder) {
StatefulRedisPubSubConnection<String, String> connection = client.connectPubSub();
RedisPubSubCommands<String, String> 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()


+ 8
- 4
sentinel-extension/sentinel-datasource-redis/pom.xml Parādīt failu

@@ -13,20 +13,24 @@
<packaging>jar</packaging>

<properties>
<java.source.version>1.8</java.source.version>
<java.target.version>1.8</java.target.version>
<lettuce.version>5.0.1.RELEASE</lettuce.version>
<redis.mock.version>0.1.6</redis.mock.version>
</properties>

<dependencies>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-extension</artifactId>
</dependency>

<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>${lettuce.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-extension</artifactId>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>


+ 43
- 30
sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/RedisDataSource.java Parādīt failu

@@ -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;

/**
* <p>
* A read-only {@code DataSource} with Redis backend.
* </p>
* <p>
* 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.
* </p>
* <p>
* Note that for consistency, users should publish the value and save the value to the ruleKey simultaneously
* like this (using Redis transaction):
* <pre>
* MULTI
* SET ruleKey value
* PUBLISH channel value
* EXEC
* </pre>
* </p>
*
* @author tiger
*/

public class RedisDataSource<T> extends AbstractDataSource<String, T> {

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 <code>ruleKey<code>`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<String, T> parser) {
public RedisDataSource(RedisConnectionConfig connectionConfig, String ruleKey, String channel,
Converter<String, T> 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<T> extends AbstractDataSource<String, T> {
}

/**
* 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<T> extends AbstractDataSource<String, T> {
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<T> extends AbstractDataSource<String, T> {
}

@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<String, String> 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<T> extends AbstractDataSource<String, T> {

@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));
}
}

}

+ 12
- 12
sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/config/RedisConnectionConfig.java Parādīt failu

@@ -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);


+ 2
- 2
sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/config/RedisHostAndPort.java Parādīt failu

@@ -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);
}



+ 0
- 81
sentinel-extension/sentinel-datasource-redis/src/main/java/com/alibaba/csp/sentinel/datasource/redis/util/AssertUtil.java Parādīt failu

@@ -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);
}
}
}

+ 18
- 18
sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/RedisConnectionConfigTest.java Parādīt failu

@@ -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());
}

}

+ 23
- 21
sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/SentinelModeRedisDataSourceTest.java Parādīt failu

@@ -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<String, List<FlowRule>> 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<String, List<FlowRule>> redisDataSource = new RedisDataSource<List<FlowRule>>(config, ruleKey, channel, flowConfigParser);
ReadableDataSource<String, List<FlowRule>> 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<String, String> subCommands = client.connect().sync();
subCommands.multi();
subCommands.set(ruleKey, flowRulesJson);
@@ -97,20 +102,17 @@ public class SentinelModeRedisDataSourceTest {
}

private Converter<String, List<FlowRule>> buildFlowConfigParser() {
return new Converter<String, List<FlowRule>>() {
@Override
public List<FlowRule> convert(String source) {
return JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
});
}
};
return source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {});
}

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<String, String> stringRedisCommands = client.connect().sync();
String ok = stringRedisCommands.set(ruleKey, flowRulesJson);
Assert.assertTrue(ok.equals("OK"));
Assert.assertEquals("OK", ok);
}
}

sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/StandLoneRedisDataSourceTest.java → sentinel-extension/sentinel-datasource-redis/src/test/java/com/alibaba/csp/sentinel/datasource/redis/StandaloneRedisDataSourceTest.java Parādīt failu

@@ -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<String, List<FlowRule>> 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<String, List<FlowRule>> redisDataSource = new RedisDataSource<List<FlowRule>>(config, ruleKey, channel, flowConfigParser);
ReadableDataSource<String, List<FlowRule>> redisDataSource = new RedisDataSource<List<FlowRule>>(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<String, String> 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<String, String> subCommands = connection.sync();
subCommands.multi();
subCommands.set(ruleKey, flowRules);
@@ -113,7 +119,7 @@ public class StandLoneRedisDataSourceTest {
RedisCommands<String, String> 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<String, List<FlowRule>> buildFlowConfigParser() {
return new Converter<String, List<FlowRule>>() {
@Override
public List<FlowRule> convert(String source) {
return JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
});
}
};
return source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {});
}

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<String, String> stringRedisCommands = client.connect().sync();
String ok = stringRedisCommands.set(ruleKey, flowRulesJson);

Notiek ielāde…
Atcelt
Saglabāt