diff --git a/pom.xml b/pom.xml index 1327368f56..6c2f6d1672 100755 --- a/pom.xml +++ b/pom.xml @@ -86,6 +86,11 @@ sentinel-datasource-extension ${project.version} + + com.alibaba.csp + sentinel-datasource-nacos + ${project.version} + com.alibaba.csp sentinel-adapter diff --git a/sentinel-demo/pom.xml b/sentinel-demo/pom.xml index 917a3c0c74..8accce646c 100755 --- a/sentinel-demo/pom.xml +++ b/sentinel-demo/pom.xml @@ -17,6 +17,7 @@ sentinel-demo-dynamic-file-rule sentinel-demo-rocketmq sentinel-demo-dubbo + sentinel-demo-nacos-datasource @@ -24,10 +25,6 @@ com.alibaba.csp sentinel-core - - com.alibaba.csp - sentinel-datasource-extension - \ No newline at end of file diff --git a/sentinel-demo/sentinel-demo-dynamic-file-rule/pom.xml b/sentinel-demo/sentinel-demo-dynamic-file-rule/pom.xml index 996cbca295..9e452525ae 100755 --- a/sentinel-demo/sentinel-demo-dynamic-file-rule/pom.xml +++ b/sentinel-demo/sentinel-demo-dynamic-file-rule/pom.xml @@ -19,6 +19,11 @@ com.alibaba.csp sentinel-datasource-extension + + + com.alibaba + fastjson + \ No newline at end of file diff --git a/sentinel-demo/sentinel-demo-nacos-datasource/pom.xml b/sentinel-demo/sentinel-demo-nacos-datasource/pom.xml new file mode 100644 index 0000000000..2c29b49748 --- /dev/null +++ b/sentinel-demo/sentinel-demo-nacos-datasource/pom.xml @@ -0,0 +1,48 @@ + + + + sentinel-demo + com.alibaba.csp + 0.1.1-SNAPSHOT + + 4.0.0 + + sentinel-demo-nacos-datasource + + + + com.alibaba.csp + sentinel-core + + + com.alibaba.csp + sentinel-datasource-extension + + + com.alibaba.csp + sentinel-datasource-nacos + + + + com.alibaba + fastjson + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven.compiler.version} + + 1.8 + 1.8 + ${java.encoding} + + + + + \ No newline at end of file diff --git a/sentinel-demo/sentinel-demo-nacos-datasource/src/main/java/com/alibaba/csp/sentinel/demo/datasource/nacos/FlowQpsRunner.java b/sentinel-demo/sentinel-demo-nacos-datasource/src/main/java/com/alibaba/csp/sentinel/demo/datasource/nacos/FlowQpsRunner.java new file mode 100644 index 0000000000..c7f37baf41 --- /dev/null +++ b/sentinel-demo/sentinel-demo-nacos-datasource/src/main/java/com/alibaba/csp/sentinel/demo/datasource/nacos/FlowQpsRunner.java @@ -0,0 +1,139 @@ +/* + * 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.demo.datasource.nacos; + +import java.util.Random; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import com.alibaba.csp.sentinel.Entry; +import com.alibaba.csp.sentinel.SphU; +import com.alibaba.csp.sentinel.slots.block.BlockException; +import com.alibaba.csp.sentinel.util.TimeUtil; + +/** + * Flow QPS runner. + * + * @author Carpenter Lee + * @author Eric Zhao + */ +class FlowQpsRunner { + + private final String resourceName; + private final int threadCount; + private int seconds; + + public FlowQpsRunner(String resourceName, int threadCount, int seconds) { + this.resourceName = resourceName; + this.threadCount = threadCount; + this.seconds = seconds; + } + + private final AtomicInteger pass = new AtomicInteger(); + private final AtomicInteger block = new AtomicInteger(); + private final AtomicInteger total = new AtomicInteger(); + + private volatile boolean stop = false; + + public void simulateTraffic() { + for (int i = 0; i < threadCount; i++) { + Thread t = new Thread(new RunTask()); + t.setName("simulate-traffic-Task"); + t.start(); + } + } + + public void tick() { + Thread timer = new Thread(new TimerTask()); + timer.setName("sentinel-timer-task"); + timer.start(); + } + + final class RunTask implements Runnable { + @Override + public void run() { + while (!stop) { + Entry entry = null; + + try { + entry = SphU.entry(resourceName); + // token acquired, means pass + pass.addAndGet(1); + } catch (BlockException e1) { + block.incrementAndGet(); + } catch (Exception e2) { + // biz exception + } finally { + total.incrementAndGet(); + if (entry != null) { + entry.exit(); + } + } + + Random random2 = new Random(); + try { + TimeUnit.MILLISECONDS.sleep(random2.nextInt(50)); + } catch (InterruptedException e) { + // ignore + } + } + } + } + + final class TimerTask implements Runnable { + @Override + public void run() { + long start = System.currentTimeMillis(); + System.out.println("begin to statistic!!!"); + + long oldTotal = 0; + long oldPass = 0; + long oldBlock = 0; + while (!stop) { + try { + TimeUnit.SECONDS.sleep(1); + } catch (InterruptedException e) { + } + long globalTotal = total.get(); + long oneSecondTotal = globalTotal - oldTotal; + oldTotal = globalTotal; + + long globalPass = pass.get(); + long oneSecondPass = globalPass - oldPass; + oldPass = globalPass; + + long globalBlock = block.get(); + long oneSecondBlock = globalBlock - oldBlock; + oldBlock = globalBlock; + + System.out.println(seconds + " send qps is: " + oneSecondTotal); + System.out.println(TimeUtil.currentTimeMillis() + ", total:" + oneSecondTotal + + ", pass:" + oneSecondPass + + ", block:" + oneSecondBlock); + + if (seconds-- <= 0) { + stop = true; + } + } + + long cost = System.currentTimeMillis() - start; + System.out.println("time cost: " + cost + " ms"); + System.out.println("total:" + total.get() + ", pass:" + pass.get() + + ", block:" + block.get()); + System.exit(0); + } + } +} diff --git a/sentinel-demo/sentinel-demo-nacos-datasource/src/main/java/com/alibaba/csp/sentinel/demo/datasource/nacos/NacosConfigSender.java b/sentinel-demo/sentinel-demo-nacos-datasource/src/main/java/com/alibaba/csp/sentinel/demo/datasource/nacos/NacosConfigSender.java new file mode 100644 index 0000000000..327c5c06e3 --- /dev/null +++ b/sentinel-demo/sentinel-demo-nacos-datasource/src/main/java/com/alibaba/csp/sentinel/demo/datasource/nacos/NacosConfigSender.java @@ -0,0 +1,45 @@ +/* + * 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.demo.datasource.nacos; + +import com.alibaba.nacos.api.NacosFactory; +import com.alibaba.nacos.api.config.ConfigService; + +/** + * Nacos config sender for demo. + * + * @author Eric Zhao + */ +public class NacosConfigSender { + + public static void main(String[] args) throws Exception { + final String remoteAddress = "localhost"; + final String groupId = "Sentinel:Demo"; + final String dataId = "com.alibaba.csp.sentinel.demo.flow.rule"; + final String rule = "[\n" + + " {\n" + + " \"resource\": \"TestResource\",\n" + + " \"controlBehavior\": 0,\n" + + " \"count\": 5.0,\n" + + " \"grade\": 1,\n" + + " \"limitApp\": \"default\",\n" + + " \"strategy\": 0\n" + + " }\n" + + "]"; + ConfigService configService = NacosFactory.createConfigService(remoteAddress); + System.out.println(configService.publishConfig(dataId, groupId, rule)); + } +} diff --git a/sentinel-demo/sentinel-demo-nacos-datasource/src/main/java/com/alibaba/csp/sentinel/demo/datasource/nacos/NacosDataSourceDemo.java b/sentinel-demo/sentinel-demo-nacos-datasource/src/main/java/com/alibaba/csp/sentinel/demo/datasource/nacos/NacosDataSourceDemo.java new file mode 100644 index 0000000000..dcaf1a950a --- /dev/null +++ b/sentinel-demo/sentinel-demo-nacos-datasource/src/main/java/com/alibaba/csp/sentinel/demo/datasource/nacos/NacosDataSourceDemo.java @@ -0,0 +1,56 @@ +/* + * 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.demo.datasource.nacos; + +import java.util.List; + +import com.alibaba.csp.sentinel.datasource.DataSource; +import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource; +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; + +/** + * This demo demonstrates how to use Nacos as the data source of Sentinel rules. + * + * Before you start, you need to start a Nacos server in local first, and then + * use {@link NacosConfigSender} to publish initial rule configuration to Nacos. + * + * @author Eric Zhao + */ +public class NacosDataSourceDemo { + + private static final String KEY = "TestResource"; + + public static void main(String[] args) { + loadRules(); + // Assume we config: resource is `TestResource`, initial QPS threshold is 5. + FlowQpsRunner runner = new FlowQpsRunner(KEY, 1, 100); + runner.simulateTraffic(); + runner.tick(); + } + + private static void loadRules() { + final String remoteAddress = "localhost"; + final String groupId = "Sentinel:Demo"; + final String dataId = "com.alibaba.csp.sentinel.demo.flow.rule"; + + DataSource> flowRuleDataSource = new NacosDataSource<>(remoteAddress, groupId, dataId, + source -> JSON.parseObject(source, new TypeReference>() {})); + FlowRuleManager.register2Property(flowRuleDataSource.getProperty()); + } +}