From c12f016b389a7c611f104538c5fe55afb32f8735 Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Fri, 4 Jan 2019 14:17:35 +0800 Subject: [PATCH] Polish cluster flow control demo to be more instructive - Add a demo Spring Boot application integrated with cluster flow control to show the recommended way Signed-off-by: Eric Zhao --- sentinel-demo/sentinel-demo-cluster/pom.xml | 34 +--- .../sentinel-demo-cluster-embedded/pom.xml | 65 ++++++ .../sentinel/demo/cluster/DemoConstants.java | 30 +++ .../cluster/app/ClusterDemoApplication.java | 30 +++ .../demo/cluster/app/config/AopConfig.java | 35 ++++ .../app/controller/ClusterDemoController.java | 38 ++++ .../demo/cluster/app/service/DemoService.java | 39 ++++ .../cluster/entity/ClusterGroupEntity.java | 77 ++++++++ .../cluster/init/DemoClusterInitFunc.java | 187 ++++++++++++++++++ .../com.alibaba.csp.sentinel.init.InitFunc | 1 + .../pom.xml | 39 ++++ .../demo/cluster/ClusterServerDemo.java | 6 +- .../sentinel/demo/cluster/DemoConstants.java | 0 .../init/DemoClusterServerInitFunc.java | 0 .../com.alibaba.csp.sentinel.init.InitFunc | 1 + .../demo/cluster/ClusterClientDemo.java | 61 ------ .../init/DemoClusterClientInitFunc.java | 57 ------ .../com.alibaba.csp.sentinel.init.InitFunc | 2 - 18 files changed, 550 insertions(+), 152 deletions(-) create mode 100644 sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/pom.xml create mode 100644 sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/DemoConstants.java create mode 100644 sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/app/ClusterDemoApplication.java create mode 100644 sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/app/config/AopConfig.java create mode 100644 sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/app/controller/ClusterDemoController.java create mode 100644 sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/app/service/DemoService.java create mode 100644 sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/entity/ClusterGroupEntity.java create mode 100644 sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/init/DemoClusterInitFunc.java create mode 100755 sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.init.InitFunc create mode 100644 sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-server-alone/pom.xml rename sentinel-demo/sentinel-demo-cluster/{ => sentinel-demo-cluster-server-alone}/src/main/java/com/alibaba/csp/sentinel/demo/cluster/ClusterServerDemo.java (90%) rename sentinel-demo/sentinel-demo-cluster/{ => sentinel-demo-cluster-server-alone}/src/main/java/com/alibaba/csp/sentinel/demo/cluster/DemoConstants.java (100%) rename sentinel-demo/sentinel-demo-cluster/{ => sentinel-demo-cluster-server-alone}/src/main/java/com/alibaba/csp/sentinel/demo/cluster/init/DemoClusterServerInitFunc.java (100%) create mode 100755 sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-server-alone/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.init.InitFunc delete mode 100644 sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/ClusterClientDemo.java delete mode 100644 sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/init/DemoClusterClientInitFunc.java delete mode 100755 sentinel-demo/sentinel-demo-cluster/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.init.InitFunc diff --git a/sentinel-demo/sentinel-demo-cluster/pom.xml b/sentinel-demo/sentinel-demo-cluster/pom.xml index 742ac0fc..bf656175 100644 --- a/sentinel-demo/sentinel-demo-cluster/pom.xml +++ b/sentinel-demo/sentinel-demo-cluster/pom.xml @@ -10,35 +10,11 @@ 4.0.0 sentinel-demo-cluster + pom - - - com.alibaba.csp - sentinel-core - - - com.alibaba.csp - sentinel-transport-simple-http - - - com.alibaba.csp - sentinel-parameter-flow-control - + + sentinel-demo-cluster-embedded + sentinel-demo-cluster-server-alone + - - 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/sentinel-demo-cluster-embedded/pom.xml b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/pom.xml new file mode 100644 index 00000000..251b7ac1 --- /dev/null +++ b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/pom.xml @@ -0,0 +1,65 @@ + + + + sentinel-demo-cluster + com.alibaba.csp + 1.4.1-SNAPSHOT + + 4.0.0 + + sentinel-demo-cluster-embedded + + + 2.0.5.RELEASE + + + + + 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 + + + + + com.alibaba.csp + sentinel-annotation-aspectj + + + org.springframework.boot + spring-boot-starter-aop + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-web + ${spring.boot.version} + + + \ No newline at end of file diff --git a/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/DemoConstants.java b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/DemoConstants.java new file mode 100644 index 00000000..7dc07402 --- /dev/null +++ b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/DemoConstants.java @@ -0,0 +1,30 @@ +/* + * 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 FLOW_POSTFIX = "-flow-rules"; + public static final String PARAM_FLOW_POSTFIX = "-param-rules"; + public static final String SERVER_NAMESPACE_SET_POSTFIX = "-cs-namespace-set"; + public static final String CLIENT_CONFIG_POSTFIX = "-cc-config"; + public static final String CLUSTER_MAP_POSTFIX = "-cluster-map"; + + private DemoConstants() {} +} diff --git a/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/app/ClusterDemoApplication.java b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/app/ClusterDemoApplication.java new file mode 100644 index 00000000..b290e5dc --- /dev/null +++ b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/app/ClusterDemoApplication.java @@ -0,0 +1,30 @@ +/* + * 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.app; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author Eric Zhao + */ +@SpringBootApplication +public class ClusterDemoApplication { + + public static void main(String[] args) { + SpringApplication.run(ClusterDemoApplication.class, args); + } +} diff --git a/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/app/config/AopConfig.java b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/app/config/AopConfig.java new file mode 100644 index 00000000..9324434a --- /dev/null +++ b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/app/config/AopConfig.java @@ -0,0 +1,35 @@ +/* + * 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.app.config; + +import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * AOP config to enable annotation support for Sentinel. + * + * @author Eric Zhao + */ +@Configuration +public class AopConfig { + + @Bean + public SentinelResourceAspect sentinelResourceAspect() { + return new SentinelResourceAspect(); + } +} diff --git a/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/app/controller/ClusterDemoController.java b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/app/controller/ClusterDemoController.java new file mode 100644 index 00000000..fae9fc2b --- /dev/null +++ b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/app/controller/ClusterDemoController.java @@ -0,0 +1,38 @@ +/* + * 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.app.controller; + +import com.alibaba.csp.sentinel.demo.cluster.app.service.DemoService; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author Eric Zhao + */ +@RestController +public class ClusterDemoController { + + @Autowired + private DemoService service; + + @GetMapping("/hello/{name}") + public String apiHello(@PathVariable String name) throws Exception { + return service.sayHello(name); + } +} diff --git a/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/app/service/DemoService.java b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/app/service/DemoService.java new file mode 100644 index 00000000..ba0d5404 --- /dev/null +++ b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/app/service/DemoService.java @@ -0,0 +1,39 @@ +/* + * 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.app.service; + +import com.alibaba.csp.sentinel.annotation.SentinelResource; +import com.alibaba.csp.sentinel.slots.block.BlockException; + +import org.springframework.stereotype.Service; + +/** + * @author Eric Zhao + */ +@Service +public class DemoService { + + @SentinelResource(blockHandler = "sayHelloBlockHandler") + public String sayHello(String name) { + return "Hello, " + name; + } + + public String sayHelloBlockHandler(String name, BlockException ex) { + // This is the block handler. + ex.printStackTrace(); + return String.format("Oops, <%s> blocked by Sentinel", name); + } +} diff --git a/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/entity/ClusterGroupEntity.java b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/entity/ClusterGroupEntity.java new file mode 100644 index 00000000..c57eba90 --- /dev/null +++ b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/entity/ClusterGroupEntity.java @@ -0,0 +1,77 @@ +/* + * 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.entity; + +import java.util.Set; + +/** + * @author Eric Zhao + * @since 1.4.1 + */ +public class ClusterGroupEntity { + + private String machineId; + private String ip; + private Integer port; + + private Set clientSet; + + public String getMachineId() { + return machineId; + } + + public ClusterGroupEntity setMachineId(String machineId) { + this.machineId = machineId; + return this; + } + + public String getIp() { + return ip; + } + + public ClusterGroupEntity setIp(String ip) { + this.ip = ip; + return this; + } + + public Integer getPort() { + return port; + } + + public ClusterGroupEntity setPort(Integer port) { + this.port = port; + return this; + } + + public Set getClientSet() { + return clientSet; + } + + public ClusterGroupEntity setClientSet(Set clientSet) { + this.clientSet = clientSet; + return this; + } + + @Override + public String toString() { + return "ClusterGroupEntity{" + + "machineId='" + machineId + '\'' + + ", ip='" + ip + '\'' + + ", port=" + port + + ", clientSet=" + clientSet + + '}'; + } +} diff --git a/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/init/DemoClusterInitFunc.java b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/init/DemoClusterInitFunc.java new file mode 100644 index 00000000..59ef0cda --- /dev/null +++ b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/java/com/alibaba/csp/sentinel/demo/cluster/init/DemoClusterInitFunc.java @@ -0,0 +1,187 @@ +/* + * 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.Optional; + +import com.alibaba.csp.sentinel.cluster.ClusterStateManager; +import com.alibaba.csp.sentinel.cluster.client.config.ClusterClientAssignConfig; +import com.alibaba.csp.sentinel.cluster.client.config.ClusterClientConfig; +import com.alibaba.csp.sentinel.cluster.client.config.ClusterClientConfigManager; +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.demo.cluster.entity.ClusterGroupEntity; +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.csp.sentinel.transport.config.TransportConfig; +import com.alibaba.csp.sentinel.util.AppNameUtil; +import com.alibaba.csp.sentinel.util.HostNameUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.TypeReference; + +/** + * @author Eric Zhao + */ +public class DemoClusterInitFunc implements InitFunc { + + private static final String APP_NAME = AppNameUtil.getAppName(); + + private final String remoteAddress = "localhost"; + private final String groupId = "SENTINEL_GROUP"; + + private final String flowDataId = APP_NAME + DemoConstants.FLOW_POSTFIX; + private final String paramDataId = APP_NAME + DemoConstants.PARAM_FLOW_POSTFIX; + private final String configDataId = APP_NAME + "-cluster-client-config"; + private final String clusterMapDataId = APP_NAME + DemoConstants.CLUSTER_MAP_POSTFIX; + + @Override + public void init() throws Exception { + // Init token client related data source. + initDynamicRuleProperty(); + + initClientConfigProperty(); + initClientServerAssignProperty(); + + // Init token server related data source. + registerClusterRuleSupplier(); + initServerTransportConfigProperty(); + + // Init cluster state property for extracting mode from cluster map data source. + initStateProperty(); + } + + private void initDynamicRuleProperty() { + 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()); + } + + private void initClientConfigProperty() { + ReadableDataSource clientConfigDs = new NacosDataSource<>(remoteAddress, groupId, + configDataId, source -> JSON.parseObject(source, new TypeReference() {})); + ClusterClientConfigManager.registerClientConfigProperty(clientConfigDs.getProperty()); + } + + private void initServerTransportConfigProperty() { + ReadableDataSource serverTransportDs = new NacosDataSource<>(remoteAddress, groupId, + clusterMapDataId, source -> { + List groupList = JSON.parseObject(source, new TypeReference>() {}); + return Optional.ofNullable(groupList) + .flatMap(this::extractServerTransportConfig) + .orElse(null); + }); + ClusterServerConfigManager.registerServerTransportProperty(serverTransportDs.getProperty()); + } + + private void registerClusterRuleSupplier() { + // Register cluster flow rule property supplier which creates data source by namespace. + ClusterFlowRuleManager.setPropertySupplier(namespace -> { + ReadableDataSource> ds = new NacosDataSource<>(remoteAddress, groupId, + flowDataId, source -> JSON.parseObject(source, new TypeReference>() {})); + return ds.getProperty(); + }); + // Register cluster parameter flow rule property supplier which creates data source by namespace. + ClusterParamFlowRuleManager.setPropertySupplier(namespace -> { + ReadableDataSource> ds = new NacosDataSource<>(remoteAddress, groupId, + paramDataId, source -> JSON.parseObject(source, new TypeReference>() {})); + return ds.getProperty(); + }); + } + + private void initClientServerAssignProperty() { + // Cluster map format: + // [{"clientSet":["112.12.88.66@8729","112.12.88.67@8727"],"ip":"112.12.88.68","machineId":"112.12.88.68@8728","port":11111}] + // machineId: , commandPort for port exposed to Sentinel dashboard (transport module) + ReadableDataSource clientAssignDs = new NacosDataSource<>(remoteAddress, groupId, + clusterMapDataId, source -> { + List groupList = JSON.parseObject(source, new TypeReference>() {}); + return Optional.ofNullable(groupList) + .flatMap(this::extractClientAssignment) + .orElse(null); + }); + ClusterClientConfigManager.registerServerAssignProperty(clientAssignDs.getProperty()); + } + + private void initStateProperty() { + // Cluster map format: + // [{"clientSet":["112.12.88.66@8729","112.12.88.67@8727"],"ip":"112.12.88.68","machineId":"112.12.88.68@8728","port":11111}] + // machineId: , commandPort for port exposed to Sentinel dashboard (transport module) + ReadableDataSource clusterModeDs = new NacosDataSource<>(remoteAddress, groupId, + clusterMapDataId, source -> { + List groupList = JSON.parseObject(source, new TypeReference>() {}); + return Optional.ofNullable(groupList) + .map(this::extractMode) + .orElse(ClusterStateManager.CLUSTER_NOT_STARTED); + }); + ClusterStateManager.registerProperty(clusterModeDs.getProperty()); + } + + private int extractMode(List groupList) { + // If any server group machineId matches current, then it's token server. + if (groupList.stream().anyMatch(this::machineEqual)) { + return ClusterStateManager.CLUSTER_SERVER; + } + boolean canBeClient = groupList.stream() + .flatMap(e -> e.getClientSet().stream()) + .anyMatch(e -> e.equals(getCurrentMachineId())); + return canBeClient ? ClusterStateManager.CLUSTER_CLIENT : ClusterStateManager.CLUSTER_NOT_STARTED; + } + + private Optional extractServerTransportConfig(List groupList) { + return groupList.stream() + .filter(this::machineEqual) + .findAny() + .map(e -> new ServerTransportConfig().setPort(e.getPort()).setIdleSeconds(600)); + } + + private Optional extractClientAssignment(List groupList) { + if (groupList.stream().anyMatch(this::machineEqual)) { + return Optional.empty(); + } + // Build client assign config from the client set of target server group. + for (ClusterGroupEntity group : groupList) { + if (group.getClientSet().contains(getCurrentMachineId())) { + String ip = group.getIp(); + Integer port = group.getPort(); + return Optional.of(new ClusterClientAssignConfig(ip, port)); + } + } + return Optional.empty(); + } + + private boolean machineEqual(/*@Valid*/ ClusterGroupEntity group) { + return getCurrentMachineId().equals(group.getMachineId()); + } + + private String getCurrentMachineId() { + return HostNameUtil.getIp() + SEPARATOR + TransportConfig.getRuntimePort(); + } + + private static final String SEPARATOR = "@"; +} diff --git a/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.init.InitFunc b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.init.InitFunc new file mode 100755 index 00000000..18228659 --- /dev/null +++ b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.init.InitFunc @@ -0,0 +1 @@ +com.alibaba.csp.sentinel.demo.cluster.init.DemoClusterInitFunc \ No newline at end of file diff --git a/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-server-alone/pom.xml b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-server-alone/pom.xml new file mode 100644 index 00000000..1cb3529f --- /dev/null +++ b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-server-alone/pom.xml @@ -0,0 +1,39 @@ + + + + sentinel-demo-cluster + com.alibaba.csp + 1.4.1-SNAPSHOT + + 4.0.0 + + sentinel-demo-cluster-server-alone + + + + com.alibaba.csp + sentinel-core + + + com.alibaba.csp + sentinel-transport-simple-http + + + com.alibaba.csp + sentinel-parameter-flow-control + + + + 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/ClusterServerDemo.java b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-server-alone/src/main/java/com/alibaba/csp/sentinel/demo/cluster/ClusterServerDemo.java similarity index 90% rename from sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/ClusterServerDemo.java rename to sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-server-alone/src/main/java/com/alibaba/csp/sentinel/demo/cluster/ClusterServerDemo.java index 8d731f28..b1398b77 100644 --- a/sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/ClusterServerDemo.java +++ b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-server-alone/src/main/java/com/alibaba/csp/sentinel/demo/cluster/ClusterServerDemo.java @@ -23,9 +23,9 @@ 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}. + *

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 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/sentinel-demo-cluster-server-alone/src/main/java/com/alibaba/csp/sentinel/demo/cluster/DemoConstants.java similarity index 100% rename from sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/DemoConstants.java rename to sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-server-alone/src/main/java/com/alibaba/csp/sentinel/demo/cluster/DemoConstants.java 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/sentinel-demo-cluster-server-alone/src/main/java/com/alibaba/csp/sentinel/demo/cluster/init/DemoClusterServerInitFunc.java similarity index 100% rename from sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/init/DemoClusterServerInitFunc.java rename to sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-server-alone/src/main/java/com/alibaba/csp/sentinel/demo/cluster/init/DemoClusterServerInitFunc.java diff --git a/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-server-alone/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.init.InitFunc b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-server-alone/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.init.InitFunc new file mode 100755 index 00000000..3d38f81e --- /dev/null +++ b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-server-alone/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.init.InitFunc @@ -0,0 +1 @@ +com.alibaba.csp.sentinel.demo.cluster.init.DemoClusterServerInitFunc \ 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 deleted file mode 100644 index c665fc3a..00000000 --- a/sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/ClusterClientDemo.java +++ /dev/null @@ -1,61 +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.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/init/DemoClusterClientInitFunc.java b/sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/init/DemoClusterClientInitFunc.java deleted file mode 100644 index d75804be..00000000 --- a/sentinel-demo/sentinel-demo-cluster/src/main/java/com/alibaba/csp/sentinel/demo/cluster/init/DemoClusterClientInitFunc.java +++ /dev/null @@ -1,57 +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.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/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 deleted file mode 100755 index 11b70ec5..00000000 --- a/sentinel-demo/sentinel-demo-cluster/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.init.InitFunc +++ /dev/null @@ -1,2 +0,0 @@ -com.alibaba.csp.sentinel.demo.cluster.init.DemoClusterClientInitFunc -com.alibaba.csp.sentinel.demo.cluster.init.DemoClusterServerInitFunc \ No newline at end of file