@@ -22,7 +22,8 @@ | |||||
<module>sentinel-demo-apollo-datasource</module> | <module>sentinel-demo-apollo-datasource</module> | ||||
<module>sentinel-demo-annotation-spring-aop</module> | <module>sentinel-demo-annotation-spring-aop</module> | ||||
<module>sentinel-demo-parameter-flow-control</module> | <module>sentinel-demo-parameter-flow-control</module> | ||||
<module>sentinel-demo-slot-chain-spi</module> | |||||
<module>sentinel-demo-slot-spi</module> | |||||
<module>sentinel-demo-slotchain-spi</module> | |||||
<module>sentinel-demo-cluster</module> | <module>sentinel-demo-cluster</module> | ||||
<module>sentinel-demo-command-handler</module> | <module>sentinel-demo-command-handler</module> | ||||
<module>sentinel-demo-spring-webflux</module> | <module>sentinel-demo-spring-webflux</module> | ||||
@@ -1,30 +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.slot; | |||||
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotChain; | |||||
import com.alibaba.csp.sentinel.slotchain.SlotChainBuilder; | |||||
import com.alibaba.csp.sentinel.slots.DefaultSlotChainBuilder; | |||||
/** | |||||
* @author Eric Zhao | |||||
* | |||||
* @deprecated since 1.7.2, we can use @SpiOrder(-3500) to adjust the order of {@link DemoSlot}, | |||||
* this class is reserved for compatibility with older versions. | |||||
*/ | |||||
@Deprecated | |||||
public class DemoSlotChainBuilder extends DefaultSlotChainBuilder { | |||||
} |
@@ -1,2 +0,0 @@ | |||||
# Custom slot processor | |||||
com.alibaba.csp.sentinel.demo.slot.DemoSlot |
@@ -9,6 +9,5 @@ | |||||
</parent> | </parent> | ||||
<modelVersion>4.0.0</modelVersion> | <modelVersion>4.0.0</modelVersion> | ||||
<artifactId>sentinel-demo-slot-chain-spi</artifactId> | |||||
<artifactId>sentinel-demo-slot-spi</artifactId> | |||||
</project> | </project> |
@@ -20,13 +20,15 @@ import com.alibaba.csp.sentinel.SphU; | |||||
import com.alibaba.csp.sentinel.slots.block.BlockException; | import com.alibaba.csp.sentinel.slots.block.BlockException; | ||||
/** | /** | ||||
* Demo for adding custom slot. | |||||
* @see {@link DemoSlot}. | |||||
* | |||||
* @author Eric Zhao | * @author Eric Zhao | ||||
* @author cdfive | |||||
*/ | */ | ||||
public class SlotChainBuilderSpiDemo { | |||||
public class DemoApplication { | |||||
public static void main(String[] args) { | public static void main(String[] args) { | ||||
// You will see this in record.log, indicating that the custom slot chain builder is activated: | |||||
// [SlotChainProvider] Global slot chain builder resolved: com.alibaba.csp.sentinel.demo.slot.DemoSlotChainBuilder | |||||
Entry entry = null; | Entry entry = null; | ||||
try { | try { | ||||
entry = SphU.entry("abc"); | entry = SphU.entry("abc"); |
@@ -1,5 +1,5 @@ | |||||
/* | /* | ||||
* Copyright 1999-2018 Alibaba Group Holding Ltd. | |||||
* Copyright 1999-2021 Alibaba Group Holding Ltd. | |||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
* you may not use this file except in compliance with the License. | * you may not use this file except in compliance with the License. | ||||
@@ -15,23 +15,32 @@ | |||||
*/ | */ | ||||
package com.alibaba.csp.sentinel.demo.slot; | package com.alibaba.csp.sentinel.demo.slot; | ||||
import com.alibaba.csp.sentinel.Constants; | |||||
import com.alibaba.csp.sentinel.context.Context; | import com.alibaba.csp.sentinel.context.Context; | ||||
import com.alibaba.csp.sentinel.node.DefaultNode; | import com.alibaba.csp.sentinel.node.DefaultNode; | ||||
import com.alibaba.csp.sentinel.slotchain.AbstractLinkedProcessorSlot; | import com.alibaba.csp.sentinel.slotchain.AbstractLinkedProcessorSlot; | ||||
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; | import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; | ||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeSlot; | |||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowSlot; | |||||
import com.alibaba.csp.sentinel.spi.Spi; | import com.alibaba.csp.sentinel.spi.Spi; | ||||
/** | /** | ||||
* An example slot that records current context and entry resource. | |||||
* A demo slot that records current context and entry resource. | |||||
* | |||||
* Note that the value of order attribute in `@Spi` is -1500, the smaller the value, the higher the order, | |||||
* so this slot will be executed after {@link FlowSlot}(order=-2000) and before {@link DegradeSlot}(order=-1000), | |||||
* refer to the constants for slot order definitions in {@link Constants}. | |||||
* | * | ||||
* @author Eric Zhao | * @author Eric Zhao | ||||
* @author cdfive | |||||
*/ | */ | ||||
@Spi(order = -3500) | |||||
@Spi(order = -1500) | |||||
public class DemoSlot extends AbstractLinkedProcessorSlot<DefaultNode> { | public class DemoSlot extends AbstractLinkedProcessorSlot<DefaultNode> { | ||||
@Override | @Override | ||||
public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count, boolean prioritized, Object... args) | public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count, boolean prioritized, Object... args) | ||||
throws Throwable { | throws Throwable { | ||||
System.out.println("------Entering for entry on DemoSlot------"); | |||||
System.out.println("Current context: " + context.getName()); | System.out.println("Current context: " + context.getName()); | ||||
System.out.println("Current entry resource: " + context.getCurEntry().getResourceWrapper().getName()); | System.out.println("Current entry resource: " + context.getCurEntry().getResourceWrapper().getName()); | ||||
@@ -40,7 +49,9 @@ public class DemoSlot extends AbstractLinkedProcessorSlot<DefaultNode> { | |||||
@Override | @Override | ||||
public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) { | public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) { | ||||
System.out.println("Exiting for entry on DemoSlot: " + context.getCurEntry().getResourceWrapper().getName()); | |||||
System.out.println("------Exiting for entry on DemoSlot------"); | |||||
System.out.println("Current context: " + context.getName()); | |||||
System.out.println("Current entry resource: " + context.getCurEntry().getResourceWrapper().getName()); | |||||
fireExit(context, resourceWrapper, count, args); | fireExit(context, resourceWrapper, count, args); | ||||
} | } |
@@ -0,0 +1,2 @@ | |||||
# Custom ProcessorSlot | |||||
com.alibaba.csp.sentinel.demo.slot.DemoSlot |
@@ -0,0 +1,13 @@ | |||||
<?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</artifactId> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<version>1.8.2-SNAPSHOT</version> | |||||
</parent> | |||||
<modelVersion>4.0.0</modelVersion> | |||||
<artifactId>sentinel-demo-slotchain-spi</artifactId> | |||||
</project> |
@@ -0,0 +1,78 @@ | |||||
/* | |||||
* Copyright 1999-2021 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.slotchain; | |||||
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.slots.block.degrade.DegradeRule; | |||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; | |||||
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreakerStrategy; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
import java.util.concurrent.ThreadLocalRandom; | |||||
import java.util.concurrent.TimeUnit; | |||||
/** | |||||
* Demo for degrade rule using custom SlotChainBuilder {@link DemoSlotChainBuilder}. | |||||
* | |||||
* You will see this in sentinel-record.log, indicating that the custom slot chain builder is activated: | |||||
* [SlotChainProvider] Global slot chain builder resolved: com.alibaba.csp.sentinel.demo.slotchain.DemoSlotChainBuilder | |||||
* | |||||
* @author cdfive | |||||
*/ | |||||
public class DemoDegradeRuleApplication { | |||||
private static final String RESOURCE_KEY = "abc"; | |||||
public static void main(String[] args) throws Exception { | |||||
initDegradeRule(); | |||||
for (int i = 1; i <= 100; i++) { | |||||
Entry entry = null; | |||||
try { | |||||
entry = SphU.entry(RESOURCE_KEY); | |||||
TimeUnit.MILLISECONDS.sleep(ThreadLocalRandom.current().nextInt(10, 100)); | |||||
System.out.println(i + "=>" + " passed"); | |||||
} catch (BlockException ex) { | |||||
System.out.println(i + "=>" + " blocked by " + ex.getClass().getSimpleName()); | |||||
} finally { | |||||
if (entry != null) { | |||||
entry.exit(); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
private static void initDegradeRule() { | |||||
List<DegradeRule> rules = new ArrayList<>(); | |||||
DegradeRule rule = new DegradeRule(RESOURCE_KEY) | |||||
.setGrade(CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType()) | |||||
// Max allowed response time | |||||
.setCount(20) | |||||
// Retry timeout (in second) | |||||
.setTimeWindow(10) | |||||
// Circuit breaker opens when slow request ratio > 20% | |||||
.setSlowRatioThreshold(0.2) | |||||
.setMinRequestAmount(10) | |||||
.setStatIntervalMs(20000); | |||||
rules.add(rule); | |||||
DegradeRuleManager.loadRules(rules); | |||||
System.out.println("Degrade rule loaded: " + rules); | |||||
} | |||||
} |
@@ -0,0 +1,76 @@ | |||||
/* | |||||
* Copyright 1999-2021 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.slotchain; | |||||
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.slots.block.RuleConstant; | |||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; | |||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; | |||||
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreakerStrategy; | |||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; | |||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
import java.util.concurrent.ThreadLocalRandom; | |||||
import java.util.concurrent.TimeUnit; | |||||
/** | |||||
* Demo for flow rule using custom SlotChainBuilder {@link DemoSlotChainBuilder}. | |||||
* | |||||
* You will see this in sentinel-record.log, indicating that the custom slot chain builder is activated: | |||||
* [SlotChainProvider] Global slot chain builder resolved: com.alibaba.csp.sentinel.demo.slotchain.DemoSlotChainBuilder | |||||
* | |||||
* @author cdfive | |||||
*/ | |||||
public class DemoFlowRuleApplication { | |||||
private static final String RESOURCE_KEY = "abc"; | |||||
public static void main(String[] args) throws Exception { | |||||
initFlowQpsRule(); | |||||
for (int i = 1; i <= 100; i++) { | |||||
Entry entry = null; | |||||
try { | |||||
entry = SphU.entry(RESOURCE_KEY); | |||||
TimeUnit.MILLISECONDS.sleep(ThreadLocalRandom.current().nextInt(10, 100)); | |||||
System.out.println(i + "=>" + " passed"); | |||||
} catch (BlockException ex) { | |||||
System.out.println(i + "=>" + " blocked by " + ex.getClass().getSimpleName()); | |||||
} finally { | |||||
if (entry != null) { | |||||
entry.exit(); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
private static void initFlowQpsRule() { | |||||
List<FlowRule> rules = new ArrayList<FlowRule>(); | |||||
FlowRule rule1 = new FlowRule(); | |||||
rule1.setResource(RESOURCE_KEY); | |||||
// set limit qps to 5 | |||||
rule1.setCount(5); | |||||
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS); | |||||
rule1.setLimitApp("default"); | |||||
rules.add(rule1); | |||||
FlowRuleManager.loadRules(rules); | |||||
System.out.println("Flow rule loaded: " + rules); | |||||
} | |||||
} |
@@ -0,0 +1,99 @@ | |||||
/* | |||||
* Copyright 1999-2021 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.slotchain; | |||||
import com.alibaba.csp.sentinel.Constants; | |||||
import com.alibaba.csp.sentinel.log.RecordLog; | |||||
import com.alibaba.csp.sentinel.slotchain.*; | |||||
import com.alibaba.csp.sentinel.slots.DefaultSlotChainBuilder; | |||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeSlot; | |||||
import com.alibaba.csp.sentinel.spi.Spi; | |||||
import com.alibaba.csp.sentinel.spi.SpiLoader; | |||||
import java.util.List; | |||||
/** | |||||
* A demo {@link SlotChainBuilder} for build custom slot chain. | |||||
* Two ways to build slot chain are demonstrated. | |||||
* | |||||
* Pay attention to that `ProcessorSlotChain` is not a SPI, but the `SlotChainBuilder`. | |||||
* | |||||
* Most of the time, we don't need to customize `SlotChainBuilder`, | |||||
* maybe customize `ProcessorSlot` is enough, refer to `sentinel-demo-slot-spi` module. | |||||
* | |||||
* Note that the sentinel's default slots and the order of them are very important, be careful when customizing, | |||||
* refer to the constants for slot order definitions in {@link Constants}. | |||||
* You may also refer to {@link DefaultSlotChainBuilder}. | |||||
* | |||||
* @author cdfive | |||||
*/ | |||||
@Spi | |||||
public class DemoSlotChainBuilder implements SlotChainBuilder { | |||||
@Override | |||||
public ProcessorSlotChain build() { | |||||
ProcessorSlotChain chain = new DefaultProcessorSlotChain(); | |||||
List<ProcessorSlot> sortedSlotList = SpiLoader.of(ProcessorSlot.class).loadInstanceListSorted(); | |||||
// Filter out `DegradeSlot` | |||||
// Test for `DemoDegradeRuleApplication`, the demo will not be blocked by `DegradeException` | |||||
sortedSlotList.removeIf(o -> DegradeSlot.class.equals(o.getClass())); | |||||
for (ProcessorSlot slot : sortedSlotList) { | |||||
if (!(slot instanceof AbstractLinkedProcessorSlot)) { | |||||
RecordLog.warn("The ProcessorSlot(" + slot.getClass().getCanonicalName() + ") is not an instance of AbstractLinkedProcessorSlot, can't be added into ProcessorSlotChain"); | |||||
continue; | |||||
} | |||||
chain.addLast((AbstractLinkedProcessorSlot<?>) slot); | |||||
} | |||||
return chain; | |||||
} | |||||
/** | |||||
* Another way to build the slot chain, add slot one by one with `SpiLoader#loadInstance`. | |||||
* Note that the sentinel's default slots and the order of them are very important, be careful when customizing, | |||||
* refer to the constants for slot order definitions in {@link com.alibaba.csp.sentinel.Constants}. | |||||
*/ | |||||
/* | |||||
@Override | |||||
public ProcessorSlotChain build() { | |||||
ProcessorSlotChain chain = new DefaultProcessorSlotChain(); | |||||
// Create a `SpiLoader` instance | |||||
SpiLoader<ProcessorSlot> spiLoader = SpiLoader.of(ProcessorSlot.class); | |||||
// Add `NodeSelectorSlot`, load by class | |||||
chain.addLast((AbstractLinkedProcessorSlot<?>) spiLoader.loadInstance(NodeSelectorSlot.class)); | |||||
// Add `ClusterBuilderSlot`, load by aliasname(default is classname) | |||||
chain.addLast((AbstractLinkedProcessorSlot<?>) spiLoader.loadInstance("com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot")); | |||||
// Add `StatisticSlot` | |||||
chain.addLast((AbstractLinkedProcessorSlot<?>) spiLoader.loadInstance(StatisticSlot.class)); | |||||
// Add `FlowSlot` | |||||
chain.addLast((AbstractLinkedProcessorSlot<?>) spiLoader.loadInstance(FlowSlot.class)); | |||||
// Add `DegradeSlot` | |||||
// Test for `DemoDegradeRuleApplication` | |||||
// If we don't add `DegradeSlot`, the demo will not be blocked by `DegradeException` | |||||
// If it's added, we can see the expected DegradeException | |||||
// chain.addLast((AbstractLinkedProcessorSlot<?>) spiLoader.loadInstance(DegradeSlot.class)); | |||||
return chain; | |||||
} | |||||
*/ | |||||
} |
@@ -0,0 +1,2 @@ | |||||
# Custom SlotChainBuilder to build slot chain | |||||
com.alibaba.csp.sentinel.demo.slotchain.DemoSlotChainBuilder |