diff --git a/sentinel-demo/sentinel-demo-cluster/pom.xml b/sentinel-demo/sentinel-demo-cluster/pom.xml
new file mode 100644
index 00000000..e76d8bb5
--- /dev/null
+++ b/sentinel-demo/sentinel-demo-cluster/pom.xml
@@ -0,0 +1,44 @@
+
+
+
+ sentinel-demo
+ com.alibaba.csp
+ 1.4.0-SNAPSHOT
+
+ 4.0.0
+
+ sentinel-demo-cluster
+
+
+
+ com.alibaba.csp
+ sentinel-core
+
+
+ com.alibaba.csp
+ sentinel-transport-simple-http
+
+
+ com.alibaba.csp
+ sentinel-parameter-flow-control
+
+
+
+ com.alibaba.csp
+ sentinel-cluster-client-default
+ ${project.version}
+
+
+ com.alibaba.csp
+ sentinel-cluster-server-default
+ ${project.version}
+
+
+
+ com.alibaba.csp
+ sentinel-datasource-nacos
+
+
+
\ No newline at end of file
diff --git a/sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/ClusterClientDemo.java b/sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/ClusterClientDemo.java
new file mode 100644
index 00000000..c665fc3a
--- /dev/null
+++ b/sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/ClusterClientDemo.java
@@ -0,0 +1,61 @@
+/*
+ * 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.cluster;
+
+import com.alibaba.csp.sentinel.Entry;
+import com.alibaba.csp.sentinel.EntryType;
+import com.alibaba.csp.sentinel.SphU;
+import com.alibaba.csp.sentinel.cluster.ClusterStateManager;
+import com.alibaba.csp.sentinel.init.InitExecutor;
+import com.alibaba.csp.sentinel.slots.block.BlockException;
+
+/**
+ * Run this demo with the following args: -Dproject.name=appA
+ *
+ * @author Eric Zhao
+ */
+public class ClusterClientDemo {
+
+ public static void main(String[] args) {
+ InitExecutor.doInit();
+
+ // Manually schedule the cluster mode to client.
+ // In common, we need a scheduling system to modify the cluster mode automatically.
+ // Command HTTP API: http://:/setClusterMode?mode=
+ ClusterStateManager.setToClient();
+
+ String resourceName = "cluster-demo-entry";
+
+ // Assume we have a cluster flow rule for `demo-resource`: QPS = 5 in AVG_LOCAL mode.
+ for (int i = 0; i < 10; i++) {
+ tryEntry(resourceName);
+ }
+ }
+
+ private static void tryEntry(String res) {
+ Entry entry = null;
+ try {
+ entry = SphU.entry(res, EntryType.IN, 1, "abc", "def");
+ System.out.println("Passed");
+ } catch (BlockException ex) {
+ ex.printStackTrace();
+ } finally {
+ if (entry != null) {
+ entry.exit();
+ }
+ }
+ }
+}
diff --git a/sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/ClusterServerDemo.java b/sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/ClusterServerDemo.java
new file mode 100644
index 00000000..8d731f28
--- /dev/null
+++ b/sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/ClusterServerDemo.java
@@ -0,0 +1,50 @@
+/*
+ * 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.cluster;
+
+import java.util.Collections;
+
+import com.alibaba.csp.sentinel.cluster.server.ClusterTokenServer;
+import com.alibaba.csp.sentinel.cluster.server.SentinelDefaultTokenServer;
+import com.alibaba.csp.sentinel.cluster.server.config.ClusterServerConfigManager;
+import com.alibaba.csp.sentinel.cluster.server.config.ServerTransportConfig;
+
+/**
+ * Cluster server demo (alone mode).
+ *
+ * Here we init the cluster server dynamic data sources in {@link com.alibaba.csp.sentinel.demo.cluster.init.DemoClusterServerInitFunc}.
+ *
+ * @author Eric Zhao
+ * @since 1.4.0
+ */
+public class ClusterServerDemo {
+
+ public static void main(String[] args) throws Exception {
+ // Not embedded mode by default (alone mode).
+ ClusterTokenServer tokenServer = new SentinelDefaultTokenServer();
+
+ // A sample for manually load config for cluster server.
+ // It's recommended to use dynamic data source to cluster manage config and rules.
+ // See the sample in DemoClusterServerInitFunc for detail.
+ ClusterServerConfigManager.loadGlobalTransportConfig(new ServerTransportConfig()
+ .setIdleSeconds(600)
+ .setPort(11111));
+ ClusterServerConfigManager.loadServerNamespaceSet(Collections.singleton(DemoConstants.APP_NAME));
+
+ // Start the server.
+ tokenServer.start();
+ }
+}
diff --git a/sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/DemoConstants.java b/sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/DemoConstants.java
new file mode 100644
index 00000000..06ee4e03
--- /dev/null
+++ b/sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/DemoConstants.java
@@ -0,0 +1,29 @@
+/*
+ * 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.cluster;
+
+/**
+ * @author Eric Zhao
+ */
+public final class DemoConstants {
+
+ public static final String APP_NAME = "appA";
+
+ public static final String FLOW_POSTFIX = "-flow-rules";
+ public static final String PARAM_FLOW_POSTFIX = "-param-rules";
+
+ private DemoConstants() {}
+}
diff --git a/sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/init/DemoClusterClientInitFunc.java b/sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/init/DemoClusterClientInitFunc.java
new file mode 100644
index 00000000..d75804be
--- /dev/null
+++ b/sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/init/DemoClusterClientInitFunc.java
@@ -0,0 +1,57 @@
+/*
+ * 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.cluster.init;
+
+import java.util.List;
+
+import com.alibaba.csp.sentinel.cluster.client.config.ClusterClientConfig;
+import com.alibaba.csp.sentinel.cluster.client.config.ClusterClientConfigManager;
+import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
+import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
+import com.alibaba.csp.sentinel.demo.cluster.DemoConstants;
+import com.alibaba.csp.sentinel.init.InitFunc;
+import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
+import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
+import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
+import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.TypeReference;
+
+/**
+ * @author Eric Zhao
+ */
+public class DemoClusterClientInitFunc implements InitFunc {
+
+ @Override
+ public void init() throws Exception {
+ final String remoteAddress = "localhost";
+ final String groupId = "SENTINEL_GROUP";
+ final String flowDataId = DemoConstants.APP_NAME + DemoConstants.FLOW_POSTFIX;
+ final String paramDataId = DemoConstants.APP_NAME + DemoConstants.PARAM_FLOW_POSTFIX;
+ final String configDataId = DemoConstants.APP_NAME + "-cluster-client-config";
+
+ ReadableDataSource> ruleSource = new NacosDataSource<>(remoteAddress, groupId,
+ flowDataId, source -> JSON.parseObject(source, new TypeReference>() {}));
+ FlowRuleManager.register2Property(ruleSource.getProperty());
+ ReadableDataSource> paramRuleSource = new NacosDataSource<>(remoteAddress, groupId,
+ paramDataId, source -> JSON.parseObject(source, new TypeReference>() {}));
+ ParamFlowRuleManager.register2Property(paramRuleSource.getProperty());
+
+ ReadableDataSource dataSource = new NacosDataSource<>(remoteAddress, groupId,
+ configDataId, source -> JSON.parseObject(source, new TypeReference() {}));
+ ClusterClientConfigManager.register2Property(dataSource.getProperty());
+ }
+}
diff --git a/sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/init/DemoClusterServerInitFunc.java b/sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/init/DemoClusterServerInitFunc.java
new file mode 100644
index 00000000..8fe5313a
--- /dev/null
+++ b/sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/init/DemoClusterServerInitFunc.java
@@ -0,0 +1,71 @@
+/*
+ * 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.cluster.init;
+
+import java.util.List;
+import java.util.Set;
+
+import com.alibaba.csp.sentinel.cluster.flow.rule.ClusterFlowRuleManager;
+import com.alibaba.csp.sentinel.cluster.flow.rule.ClusterParamFlowRuleManager;
+import com.alibaba.csp.sentinel.cluster.server.config.ClusterServerConfigManager;
+import com.alibaba.csp.sentinel.cluster.server.config.ServerTransportConfig;
+import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
+import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
+import com.alibaba.csp.sentinel.demo.cluster.DemoConstants;
+import com.alibaba.csp.sentinel.init.InitFunc;
+import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
+import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.TypeReference;
+
+/**
+ * @author Eric Zhao
+ */
+public class DemoClusterServerInitFunc implements InitFunc {
+
+ private final String remoteAddress = "localhost";
+ private final String groupId = "SENTINEL_GROUP";
+ private final String namespaceSetDataId = "cluster-server-namespace-set";
+ private final String serverTransportDataId = "cluster-server-transport-config";
+
+ @Override
+ public void init() throws Exception {
+ // Register cluster flow rule property supplier which creates data source by namespace.
+ ClusterFlowRuleManager.setPropertySupplier(namespace -> {
+ ReadableDataSource> ds = new NacosDataSource<>(remoteAddress, groupId,
+ namespace + DemoConstants.FLOW_POSTFIX,
+ source -> JSON.parseObject(source, new TypeReference>() {}));
+ return ds.getProperty();
+ });
+ // Register cluster parameter flow rule property supplier.
+ ClusterParamFlowRuleManager.setPropertySupplier(namespace -> {
+ ReadableDataSource> ds = new NacosDataSource<>(remoteAddress, groupId,
+ namespace + DemoConstants.PARAM_FLOW_POSTFIX,
+ source -> JSON.parseObject(source, new TypeReference>() {}));
+ return ds.getProperty();
+ });
+
+ // Server namespace set (scope) data source.
+ ReadableDataSource> namespaceDs = new NacosDataSource<>(remoteAddress, groupId,
+ namespaceSetDataId, source -> JSON.parseObject(source, new TypeReference>() {}));
+ ClusterServerConfigManager.registerNamespaceSetProperty(namespaceDs.getProperty());
+ // Server transport configuration data source.
+ ReadableDataSource transportConfigDs = new NacosDataSource<>(remoteAddress,
+ groupId, serverTransportDataId,
+ source -> JSON.parseObject(source, new TypeReference() {}));
+ ClusterServerConfigManager.registerServerTransportProperty(transportConfigDs.getProperty());
+ }
+}
diff --git a/sentinel-demo/sentinel-demo-cluster/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.init.InitFunc b/sentinel-demo/sentinel-demo-cluster/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.init.InitFunc
new file mode 100755
index 00000000..11b70ec5
--- /dev/null
+++ b/sentinel-demo/sentinel-demo-cluster/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.init.InitFunc
@@ -0,0 +1,2 @@
+com.alibaba.csp.sentinel.demo.cluster.init.DemoClusterClientInitFunc
+com.alibaba.csp.sentinel.demo.cluster.init.DemoClusterServerInitFunc
\ No newline at end of file