- Add a demo Spring Boot application integrated with cluster flow control to show the recommended way Signed-off-by: Eric Zhao <sczyh16@gmail.com>master
@@ -10,35 +10,11 @@ | |||||
<modelVersion>4.0.0</modelVersion> | <modelVersion>4.0.0</modelVersion> | ||||
<artifactId>sentinel-demo-cluster</artifactId> | <artifactId>sentinel-demo-cluster</artifactId> | ||||
<packaging>pom</packaging> | |||||
<dependencies> | |||||
<dependency> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<artifactId>sentinel-core</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<artifactId>sentinel-transport-simple-http</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<artifactId>sentinel-parameter-flow-control</artifactId> | |||||
</dependency> | |||||
<modules> | |||||
<module>sentinel-demo-cluster-embedded</module> | |||||
<module>sentinel-demo-cluster-server-alone</module> | |||||
</modules> | |||||
<dependency> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<artifactId>sentinel-cluster-client-default</artifactId> | |||||
<version>${project.version}</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<artifactId>sentinel-cluster-server-default</artifactId> | |||||
<version>${project.version}</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<artifactId>sentinel-datasource-nacos</artifactId> | |||||
</dependency> | |||||
</dependencies> | |||||
</project> | </project> |
@@ -0,0 +1,65 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<project xmlns="http://maven.apache.org/POM/4.0.0" | |||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||||
<parent> | |||||
<artifactId>sentinel-demo-cluster</artifactId> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<version>1.4.1-SNAPSHOT</version> | |||||
</parent> | |||||
<modelVersion>4.0.0</modelVersion> | |||||
<artifactId>sentinel-demo-cluster-embedded</artifactId> | |||||
<properties> | |||||
<spring.boot.version>2.0.5.RELEASE</spring.boot.version> | |||||
</properties> | |||||
<dependencies> | |||||
<dependency> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<artifactId>sentinel-core</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<artifactId>sentinel-transport-simple-http</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<artifactId>sentinel-parameter-flow-control</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<artifactId>sentinel-cluster-client-default</artifactId> | |||||
<version>${project.version}</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<artifactId>sentinel-cluster-server-default</artifactId> | |||||
<version>${project.version}</version> | |||||
</dependency> | |||||
<!-- Nacos for dynamic data source --> | |||||
<dependency> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<artifactId>sentinel-datasource-nacos</artifactId> | |||||
</dependency> | |||||
<!-- for a real web demo --> | |||||
<dependency> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<artifactId>sentinel-annotation-aspectj</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-aop</artifactId> | |||||
<version>${spring.boot.version}</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-web</artifactId> | |||||
<version>${spring.boot.version}</version> | |||||
</dependency> | |||||
</dependencies> | |||||
</project> |
@@ -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() {} | |||||
} |
@@ -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); | |||||
} | |||||
} |
@@ -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(); | |||||
} | |||||
} |
@@ -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); | |||||
} | |||||
} |
@@ -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); | |||||
} | |||||
} |
@@ -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<String> 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<String> getClientSet() { | |||||
return clientSet; | |||||
} | |||||
public ClusterGroupEntity setClientSet(Set<String> clientSet) { | |||||
this.clientSet = clientSet; | |||||
return this; | |||||
} | |||||
@Override | |||||
public String toString() { | |||||
return "ClusterGroupEntity{" + | |||||
"machineId='" + machineId + '\'' + | |||||
", ip='" + ip + '\'' + | |||||
", port=" + port + | |||||
", clientSet=" + clientSet + | |||||
'}'; | |||||
} | |||||
} |
@@ -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<String, List<FlowRule>> ruleSource = new NacosDataSource<>(remoteAddress, groupId, | |||||
flowDataId, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {})); | |||||
FlowRuleManager.register2Property(ruleSource.getProperty()); | |||||
ReadableDataSource<String, List<ParamFlowRule>> paramRuleSource = new NacosDataSource<>(remoteAddress, groupId, | |||||
paramDataId, source -> JSON.parseObject(source, new TypeReference<List<ParamFlowRule>>() {})); | |||||
ParamFlowRuleManager.register2Property(paramRuleSource.getProperty()); | |||||
} | |||||
private void initClientConfigProperty() { | |||||
ReadableDataSource<String, ClusterClientConfig> clientConfigDs = new NacosDataSource<>(remoteAddress, groupId, | |||||
configDataId, source -> JSON.parseObject(source, new TypeReference<ClusterClientConfig>() {})); | |||||
ClusterClientConfigManager.registerClientConfigProperty(clientConfigDs.getProperty()); | |||||
} | |||||
private void initServerTransportConfigProperty() { | |||||
ReadableDataSource<String, ServerTransportConfig> serverTransportDs = new NacosDataSource<>(remoteAddress, groupId, | |||||
clusterMapDataId, source -> { | |||||
List<ClusterGroupEntity> groupList = JSON.parseObject(source, new TypeReference<List<ClusterGroupEntity>>() {}); | |||||
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<String, List<FlowRule>> ds = new NacosDataSource<>(remoteAddress, groupId, | |||||
flowDataId, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {})); | |||||
return ds.getProperty(); | |||||
}); | |||||
// Register cluster parameter flow rule property supplier which creates data source by namespace. | |||||
ClusterParamFlowRuleManager.setPropertySupplier(namespace -> { | |||||
ReadableDataSource<String, List<ParamFlowRule>> ds = new NacosDataSource<>(remoteAddress, groupId, | |||||
paramDataId, source -> JSON.parseObject(source, new TypeReference<List<ParamFlowRule>>() {})); | |||||
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: <ip@commandPort>, commandPort for port exposed to Sentinel dashboard (transport module) | |||||
ReadableDataSource<String, ClusterClientAssignConfig> clientAssignDs = new NacosDataSource<>(remoteAddress, groupId, | |||||
clusterMapDataId, source -> { | |||||
List<ClusterGroupEntity> groupList = JSON.parseObject(source, new TypeReference<List<ClusterGroupEntity>>() {}); | |||||
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: <ip@commandPort>, commandPort for port exposed to Sentinel dashboard (transport module) | |||||
ReadableDataSource<String, Integer> clusterModeDs = new NacosDataSource<>(remoteAddress, groupId, | |||||
clusterMapDataId, source -> { | |||||
List<ClusterGroupEntity> groupList = JSON.parseObject(source, new TypeReference<List<ClusterGroupEntity>>() {}); | |||||
return Optional.ofNullable(groupList) | |||||
.map(this::extractMode) | |||||
.orElse(ClusterStateManager.CLUSTER_NOT_STARTED); | |||||
}); | |||||
ClusterStateManager.registerProperty(clusterModeDs.getProperty()); | |||||
} | |||||
private int extractMode(List<ClusterGroupEntity> 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<ServerTransportConfig> extractServerTransportConfig(List<ClusterGroupEntity> groupList) { | |||||
return groupList.stream() | |||||
.filter(this::machineEqual) | |||||
.findAny() | |||||
.map(e -> new ServerTransportConfig().setPort(e.getPort()).setIdleSeconds(600)); | |||||
} | |||||
private Optional<ClusterClientAssignConfig> extractClientAssignment(List<ClusterGroupEntity> 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 = "@"; | |||||
} |
@@ -0,0 +1 @@ | |||||
com.alibaba.csp.sentinel.demo.cluster.init.DemoClusterInitFunc |
@@ -0,0 +1,39 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<project xmlns="http://maven.apache.org/POM/4.0.0" | |||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||||
<parent> | |||||
<artifactId>sentinel-demo-cluster</artifactId> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<version>1.4.1-SNAPSHOT</version> | |||||
</parent> | |||||
<modelVersion>4.0.0</modelVersion> | |||||
<artifactId>sentinel-demo-cluster-server-alone</artifactId> | |||||
<dependencies> | |||||
<dependency> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<artifactId>sentinel-core</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<artifactId>sentinel-transport-simple-http</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<artifactId>sentinel-parameter-flow-control</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<artifactId>sentinel-cluster-server-default</artifactId> | |||||
<version>${project.version}</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<artifactId>sentinel-datasource-nacos</artifactId> | |||||
</dependency> | |||||
</dependencies> | |||||
</project> |
@@ -23,9 +23,9 @@ import com.alibaba.csp.sentinel.cluster.server.config.ClusterServerConfigManager | |||||
import com.alibaba.csp.sentinel.cluster.server.config.ServerTransportConfig; | 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}. | |||||
* <p>Cluster server demo (alone mode).</p> | |||||
* <p>Here we init the cluster server dynamic data sources in | |||||
* {@link com.alibaba.csp.sentinel.demo.cluster.init.DemoClusterServerInitFunc}.</p> | |||||
* | * | ||||
* @author Eric Zhao | * @author Eric Zhao | ||||
* @since 1.4.0 | * @since 1.4.0 |
@@ -0,0 +1 @@ | |||||
com.alibaba.csp.sentinel.demo.cluster.init.DemoClusterServerInitFunc |
@@ -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; | |||||
/** | |||||
* <p>Run this demo with the following args: -Dproject.name=appA</p> | |||||
* | |||||
* @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://<ip>:<port>/setClusterMode?mode=<xxx> | |||||
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(); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -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<String, List<FlowRule>> ruleSource = new NacosDataSource<>(remoteAddress, groupId, | |||||
flowDataId, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {})); | |||||
FlowRuleManager.register2Property(ruleSource.getProperty()); | |||||
ReadableDataSource<String, List<ParamFlowRule>> paramRuleSource = new NacosDataSource<>(remoteAddress, groupId, | |||||
paramDataId, source -> JSON.parseObject(source, new TypeReference<List<ParamFlowRule>>() {})); | |||||
ParamFlowRuleManager.register2Property(paramRuleSource.getProperty()); | |||||
ReadableDataSource<String, ClusterClientConfig> dataSource = new NacosDataSource<>(remoteAddress, groupId, | |||||
configDataId, source -> JSON.parseObject(source, new TypeReference<ClusterClientConfig>() {})); | |||||
ClusterClientConfigManager.register2Property(dataSource.getProperty()); | |||||
} | |||||
} |
@@ -1,2 +0,0 @@ | |||||
com.alibaba.csp.sentinel.demo.cluster.init.DemoClusterClientInitFunc | |||||
com.alibaba.csp.sentinel.demo.cluster.init.DemoClusterServerInitFunc |