diff --git a/sentinel-demo/pom.xml b/sentinel-demo/pom.xml index 68e06ff4..5df6d725 100755 --- a/sentinel-demo/pom.xml +++ b/sentinel-demo/pom.xml @@ -22,7 +22,8 @@ sentinel-demo-apollo-datasource sentinel-demo-annotation-spring-aop sentinel-demo-parameter-flow-control - sentinel-demo-slot-chain-spi + sentinel-demo-slot-spi + sentinel-demo-slotchain-spi sentinel-demo-cluster sentinel-demo-command-handler sentinel-demo-spring-webflux diff --git a/sentinel-demo/sentinel-demo-slot-chain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/DemoSlotChainBuilder.java b/sentinel-demo/sentinel-demo-slot-chain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/DemoSlotChainBuilder.java deleted file mode 100644 index a1494c69..00000000 --- a/sentinel-demo/sentinel-demo-slot-chain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/DemoSlotChainBuilder.java +++ /dev/null @@ -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 { -} diff --git a/sentinel-demo/sentinel-demo-slot-chain-spi/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.ProcessorSlot b/sentinel-demo/sentinel-demo-slot-chain-spi/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.ProcessorSlot deleted file mode 100644 index 49f508f3..00000000 --- a/sentinel-demo/sentinel-demo-slot-chain-spi/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.ProcessorSlot +++ /dev/null @@ -1,2 +0,0 @@ -# Custom slot processor -com.alibaba.csp.sentinel.demo.slot.DemoSlot \ No newline at end of file diff --git a/sentinel-demo/sentinel-demo-slot-chain-spi/pom.xml b/sentinel-demo/sentinel-demo-slot-spi/pom.xml similarity index 86% rename from sentinel-demo/sentinel-demo-slot-chain-spi/pom.xml rename to sentinel-demo/sentinel-demo-slot-spi/pom.xml index ff7942e1..35c1e23b 100644 --- a/sentinel-demo/sentinel-demo-slot-chain-spi/pom.xml +++ b/sentinel-demo/sentinel-demo-slot-spi/pom.xml @@ -9,6 +9,5 @@ 4.0.0 - sentinel-demo-slot-chain-spi - + sentinel-demo-slot-spi \ No newline at end of file diff --git a/sentinel-demo/sentinel-demo-slot-chain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/SlotChainBuilderSpiDemo.java b/sentinel-demo/sentinel-demo-slot-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/DemoApplication.java similarity index 81% rename from sentinel-demo/sentinel-demo-slot-chain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/SlotChainBuilderSpiDemo.java rename to sentinel-demo/sentinel-demo-slot-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/DemoApplication.java index 7eea5caf..b5a1834f 100644 --- a/sentinel-demo/sentinel-demo-slot-chain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/SlotChainBuilderSpiDemo.java +++ b/sentinel-demo/sentinel-demo-slot-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/DemoApplication.java @@ -20,13 +20,15 @@ import com.alibaba.csp.sentinel.SphU; import com.alibaba.csp.sentinel.slots.block.BlockException; /** + * Demo for adding custom slot. + * @see {@link DemoSlot}. + * * @author Eric Zhao + * @author cdfive */ -public class SlotChainBuilderSpiDemo { +public class DemoApplication { 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; try { entry = SphU.entry("abc"); diff --git a/sentinel-demo/sentinel-demo-slot-chain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/DemoSlot.java b/sentinel-demo/sentinel-demo-slot-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/DemoSlot.java similarity index 63% rename from sentinel-demo/sentinel-demo-slot-chain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/DemoSlot.java rename to sentinel-demo/sentinel-demo-slot-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/DemoSlot.java index ab15c39d..9b15eb9c 100644 --- a/sentinel-demo/sentinel-demo-slot-chain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/DemoSlot.java +++ b/sentinel-demo/sentinel-demo-slot-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/DemoSlot.java @@ -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"); * you may not use this file except in compliance with the License. @@ -15,23 +15,32 @@ */ 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.node.DefaultNode; import com.alibaba.csp.sentinel.slotchain.AbstractLinkedProcessorSlot; 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; /** - * 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 cdfive */ -@Spi(order = -3500) +@Spi(order = -1500) public class DemoSlot extends AbstractLinkedProcessorSlot { @Override public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count, boolean prioritized, Object... args) throws Throwable { + System.out.println("------Entering for entry on DemoSlot------"); System.out.println("Current context: " + context.getName()); System.out.println("Current entry resource: " + context.getCurEntry().getResourceWrapper().getName()); @@ -40,7 +49,9 @@ public class DemoSlot extends AbstractLinkedProcessorSlot { @Override 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); } diff --git a/sentinel-demo/sentinel-demo-slot-spi/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.ProcessorSlot b/sentinel-demo/sentinel-demo-slot-spi/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.ProcessorSlot new file mode 100644 index 00000000..9f0d7c7a --- /dev/null +++ b/sentinel-demo/sentinel-demo-slot-spi/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.ProcessorSlot @@ -0,0 +1,2 @@ +# Custom ProcessorSlot +com.alibaba.csp.sentinel.demo.slot.DemoSlot \ No newline at end of file diff --git a/sentinel-demo/sentinel-demo-slotchain-spi/pom.xml b/sentinel-demo/sentinel-demo-slotchain-spi/pom.xml new file mode 100644 index 00000000..b693516d --- /dev/null +++ b/sentinel-demo/sentinel-demo-slotchain-spi/pom.xml @@ -0,0 +1,13 @@ + + + + sentinel-demo + com.alibaba.csp + 1.8.2-SNAPSHOT + + 4.0.0 + + sentinel-demo-slotchain-spi + \ No newline at end of file diff --git a/sentinel-demo/sentinel-demo-slotchain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slotchain/DemoDegradeRuleApplication.java b/sentinel-demo/sentinel-demo-slotchain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slotchain/DemoDegradeRuleApplication.java new file mode 100644 index 00000000..12100d31 --- /dev/null +++ b/sentinel-demo/sentinel-demo-slotchain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slotchain/DemoDegradeRuleApplication.java @@ -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 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); + } +} diff --git a/sentinel-demo/sentinel-demo-slotchain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slotchain/DemoFlowRuleApplication.java b/sentinel-demo/sentinel-demo-slotchain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slotchain/DemoFlowRuleApplication.java new file mode 100644 index 00000000..f46650df --- /dev/null +++ b/sentinel-demo/sentinel-demo-slotchain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slotchain/DemoFlowRuleApplication.java @@ -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 rules = new ArrayList(); + 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); + } +} diff --git a/sentinel-demo/sentinel-demo-slotchain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slotchain/DemoSlotChainBuilder.java b/sentinel-demo/sentinel-demo-slotchain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slotchain/DemoSlotChainBuilder.java new file mode 100644 index 00000000..c250e4f3 --- /dev/null +++ b/sentinel-demo/sentinel-demo-slotchain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slotchain/DemoSlotChainBuilder.java @@ -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 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 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; + } + */ +} diff --git a/sentinel-demo/sentinel-demo-slotchain-spi/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.SlotChainBuilder b/sentinel-demo/sentinel-demo-slotchain-spi/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.SlotChainBuilder new file mode 100644 index 00000000..f036afbd --- /dev/null +++ b/sentinel-demo/sentinel-demo-slotchain-spi/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.SlotChainBuilder @@ -0,0 +1,2 @@ +# Custom SlotChainBuilder to build slot chain +com.alibaba.csp.sentinel.demo.slotchain.DemoSlotChainBuilder \ No newline at end of file