Browse Source

example: Add separate demo for slot/slot chain SPI (#2085)

master
cdfive GitHub 3 years ago
parent
commit
a79ef35847
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 293 additions and 42 deletions
  1. +2
    -1
      sentinel-demo/pom.xml
  2. +0
    -30
      sentinel-demo/sentinel-demo-slot-chain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/DemoSlotChainBuilder.java
  3. +0
    -2
      sentinel-demo/sentinel-demo-slot-chain-spi/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.ProcessorSlot
  4. +1
    -2
      sentinel-demo/sentinel-demo-slot-spi/pom.xml
  5. +5
    -3
      sentinel-demo/sentinel-demo-slot-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/DemoApplication.java
  6. +15
    -4
      sentinel-demo/sentinel-demo-slot-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/DemoSlot.java
  7. +2
    -0
      sentinel-demo/sentinel-demo-slot-spi/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.ProcessorSlot
  8. +13
    -0
      sentinel-demo/sentinel-demo-slotchain-spi/pom.xml
  9. +78
    -0
      sentinel-demo/sentinel-demo-slotchain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slotchain/DemoDegradeRuleApplication.java
  10. +76
    -0
      sentinel-demo/sentinel-demo-slotchain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slotchain/DemoFlowRuleApplication.java
  11. +99
    -0
      sentinel-demo/sentinel-demo-slotchain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slotchain/DemoSlotChainBuilder.java
  12. +2
    -0
      sentinel-demo/sentinel-demo-slotchain-spi/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.SlotChainBuilder

+ 2
- 1
sentinel-demo/pom.xml View File

@@ -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>


+ 0
- 30
sentinel-demo/sentinel-demo-slot-chain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/DemoSlotChainBuilder.java View File

@@ -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 {
}

+ 0
- 2
sentinel-demo/sentinel-demo-slot-chain-spi/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.ProcessorSlot View File

@@ -1,2 +0,0 @@
# Custom slot processor
com.alibaba.csp.sentinel.demo.slot.DemoSlot

sentinel-demo/sentinel-demo-slot-chain-spi/pom.xml → sentinel-demo/sentinel-demo-slot-spi/pom.xml View File

@@ -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>

sentinel-demo/sentinel-demo-slot-chain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/SlotChainBuilderSpiDemo.java → sentinel-demo/sentinel-demo-slot-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/DemoApplication.java View File

@@ -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");

sentinel-demo/sentinel-demo-slot-chain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/DemoSlot.java → sentinel-demo/sentinel-demo-slot-spi/src/main/java/com/alibaba/csp/sentinel/demo/slot/DemoSlot.java View File

@@ -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);
} }

+ 2
- 0
sentinel-demo/sentinel-demo-slot-spi/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.ProcessorSlot View File

@@ -0,0 +1,2 @@
# Custom ProcessorSlot
com.alibaba.csp.sentinel.demo.slot.DemoSlot

+ 13
- 0
sentinel-demo/sentinel-demo-slotchain-spi/pom.xml View File

@@ -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>

+ 78
- 0
sentinel-demo/sentinel-demo-slotchain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slotchain/DemoDegradeRuleApplication.java View File

@@ -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);
}
}

+ 76
- 0
sentinel-demo/sentinel-demo-slotchain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slotchain/DemoFlowRuleApplication.java View File

@@ -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);
}
}

+ 99
- 0
sentinel-demo/sentinel-demo-slotchain-spi/src/main/java/com/alibaba/csp/sentinel/demo/slotchain/DemoSlotChainBuilder.java View File

@@ -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;
}
*/
}

+ 2
- 0
sentinel-demo/sentinel-demo-slotchain-spi/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.SlotChainBuilder View File

@@ -0,0 +1,2 @@
# Custom SlotChainBuilder to build slot chain
com.alibaba.csp.sentinel.demo.slotchain.DemoSlotChainBuilder

Loading…
Cancel
Save