* Make slots loaded by SPI, mark all slots with @SpiOrder from -10000 to -1000, improve comment * Reserve gateway and param slot chain builder (just extends DefaultSlotChainBuilder) and mark them as @Deprecatedmaster
@@ -27,11 +27,13 @@ import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowChecker; | |||||
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException; | import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException; | ||||
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule; | import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule; | ||||
import com.alibaba.csp.sentinel.slots.block.flow.param.ParameterMetricStorage; | import com.alibaba.csp.sentinel.slots.block.flow.param.ParameterMetricStorage; | ||||
import com.alibaba.csp.sentinel.spi.SpiOrder; | |||||
/** | /** | ||||
* @author Eric Zhao | * @author Eric Zhao | ||||
* @since 1.6.1 | * @since 1.6.1 | ||||
*/ | */ | ||||
@SpiOrder(-4000) | |||||
public class GatewayFlowSlot extends AbstractLinkedProcessorSlot<DefaultNode> { | public class GatewayFlowSlot extends AbstractLinkedProcessorSlot<DefaultNode> { | ||||
@Override | @Override | ||||
@@ -15,43 +15,18 @@ | |||||
*/ | */ | ||||
package com.alibaba.csp.sentinel.adapter.gateway.common.slot; | package com.alibaba.csp.sentinel.adapter.gateway.common.slot; | ||||
import com.alibaba.csp.sentinel.slotchain.DefaultProcessorSlotChain; | |||||
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotChain; | |||||
import com.alibaba.csp.sentinel.slotchain.SlotChainBuilder; | |||||
import com.alibaba.csp.sentinel.slots.block.authority.AuthoritySlot; | |||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeSlot; | |||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowSlot; | |||||
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowSlot; | |||||
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot; | |||||
import com.alibaba.csp.sentinel.slots.logger.LogSlot; | |||||
import com.alibaba.csp.sentinel.slots.nodeselector.NodeSelectorSlot; | |||||
import com.alibaba.csp.sentinel.slots.statistic.StatisticSlot; | |||||
import com.alibaba.csp.sentinel.slots.system.SystemSlot; | |||||
import com.alibaba.csp.sentinel.slots.DefaultSlotChainBuilder; | |||||
/** | /** | ||||
* @author Eric Zhao | * @author Eric Zhao | ||||
* @since 1.6.1 | * @since 1.6.1 | ||||
* | |||||
* @deprecated since 1.7.2, we can use @SpiOrder(-4000) to adjust the order of {@link GatewayFlowSlot}, | |||||
* this class is reserved for compatibility with older versions. | |||||
* @see GatewayFlowSlot | |||||
* @see DefaultSlotChainBuilder | |||||
*/ | */ | ||||
public class GatewaySlotChainBuilder implements SlotChainBuilder { | |||||
@Override | |||||
public ProcessorSlotChain build() { | |||||
ProcessorSlotChain chain = new DefaultProcessorSlotChain(); | |||||
// Prepare slot | |||||
chain.addLast(new NodeSelectorSlot()); | |||||
chain.addLast(new ClusterBuilderSlot()); | |||||
// Stat slot | |||||
chain.addLast(new LogSlot()); | |||||
chain.addLast(new StatisticSlot()); | |||||
// Rule checking slot | |||||
chain.addLast(new AuthoritySlot()); | |||||
chain.addLast(new SystemSlot()); | |||||
chain.addLast(new GatewayFlowSlot()); | |||||
chain.addLast(new ParamFlowSlot()); | |||||
chain.addLast(new FlowSlot()); | |||||
chain.addLast(new DegradeSlot()); | |||||
@Deprecated | |||||
public class GatewaySlotChainBuilder extends DefaultSlotChainBuilder { | |||||
return chain; | |||||
} | |||||
} | } |
@@ -0,0 +1 @@ | |||||
com.alibaba.csp.sentinel.adapter.gateway.common.slot.GatewayFlowSlot |
@@ -1 +0,0 @@ | |||||
com.alibaba.csp.sentinel.adapter.gateway.common.slot.GatewaySlotChainBuilder |
@@ -15,17 +15,15 @@ | |||||
*/ | */ | ||||
package com.alibaba.csp.sentinel.slots; | package com.alibaba.csp.sentinel.slots; | ||||
import com.alibaba.csp.sentinel.log.RecordLog; | |||||
import com.alibaba.csp.sentinel.slotchain.AbstractLinkedProcessorSlot; | |||||
import com.alibaba.csp.sentinel.slotchain.DefaultProcessorSlotChain; | import com.alibaba.csp.sentinel.slotchain.DefaultProcessorSlotChain; | ||||
import com.alibaba.csp.sentinel.slotchain.ProcessorSlot; | |||||
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotChain; | import com.alibaba.csp.sentinel.slotchain.ProcessorSlotChain; | ||||
import com.alibaba.csp.sentinel.slotchain.SlotChainBuilder; | import com.alibaba.csp.sentinel.slotchain.SlotChainBuilder; | ||||
import com.alibaba.csp.sentinel.slots.block.authority.AuthoritySlot; | |||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeSlot; | |||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowSlot; | |||||
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot; | |||||
import com.alibaba.csp.sentinel.slots.logger.LogSlot; | |||||
import com.alibaba.csp.sentinel.slots.nodeselector.NodeSelectorSlot; | |||||
import com.alibaba.csp.sentinel.slots.statistic.StatisticSlot; | |||||
import com.alibaba.csp.sentinel.slots.system.SystemSlot; | |||||
import com.alibaba.csp.sentinel.util.SpiLoader; | |||||
import java.util.List; | |||||
/** | /** | ||||
* Builder for a default {@link ProcessorSlotChain}. | * Builder for a default {@link ProcessorSlotChain}. | ||||
@@ -38,16 +36,18 @@ public class DefaultSlotChainBuilder implements SlotChainBuilder { | |||||
@Override | @Override | ||||
public ProcessorSlotChain build() { | public ProcessorSlotChain build() { | ||||
ProcessorSlotChain chain = new DefaultProcessorSlotChain(); | ProcessorSlotChain chain = new DefaultProcessorSlotChain(); | ||||
chain.addLast(new NodeSelectorSlot()); | |||||
chain.addLast(new ClusterBuilderSlot()); | |||||
chain.addLast(new LogSlot()); | |||||
chain.addLast(new StatisticSlot()); | |||||
chain.addLast(new AuthoritySlot()); | |||||
chain.addLast(new SystemSlot()); | |||||
chain.addLast(new FlowSlot()); | |||||
chain.addLast(new DegradeSlot()); | |||||
// Note: the instances of ProcessorSlot should be different, since they are not stateless. | |||||
List<ProcessorSlot> sortedSlotList = SpiLoader.loadDifferentInstanceListSorted(ProcessorSlot.class); | |||||
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; | return chain; | ||||
} | } | ||||
} | } |
@@ -23,6 +23,7 @@ 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.ProcessorSlot; | import com.alibaba.csp.sentinel.slotchain.ProcessorSlot; | ||||
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; | import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; | ||||
import com.alibaba.csp.sentinel.spi.SpiOrder; | |||||
/** | /** | ||||
* A {@link ProcessorSlot} that dedicates to {@link AuthorityRule} checking. | * A {@link ProcessorSlot} that dedicates to {@link AuthorityRule} checking. | ||||
@@ -30,6 +31,7 @@ import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; | |||||
* @author leyou | * @author leyou | ||||
* @author Eric Zhao | * @author Eric Zhao | ||||
*/ | */ | ||||
@SpiOrder(-6000) | |||||
public class AuthoritySlot extends AbstractLinkedProcessorSlot<DefaultNode> { | public class AuthoritySlot extends AbstractLinkedProcessorSlot<DefaultNode> { | ||||
@Override | @Override | ||||
@@ -20,12 +20,14 @@ 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.ProcessorSlot; | import com.alibaba.csp.sentinel.slotchain.ProcessorSlot; | ||||
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; | import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; | ||||
import com.alibaba.csp.sentinel.spi.SpiOrder; | |||||
/** | /** | ||||
* A {@link ProcessorSlot} dedicates to {@link DegradeRule} checking. | * A {@link ProcessorSlot} dedicates to {@link DegradeRule} checking. | ||||
* | * | ||||
* @author leyou | * @author leyou | ||||
*/ | */ | ||||
@SpiOrder(-1000) | |||||
public class DegradeSlot extends AbstractLinkedProcessorSlot<DefaultNode> { | public class DegradeSlot extends AbstractLinkedProcessorSlot<DefaultNode> { | ||||
@Override | @Override | ||||
@@ -15,18 +15,19 @@ | |||||
*/ | */ | ||||
package com.alibaba.csp.sentinel.slots.block.flow; | package com.alibaba.csp.sentinel.slots.block.flow; | ||||
import java.util.Collection; | |||||
import java.util.List; | |||||
import java.util.Map; | |||||
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.BlockException; | import com.alibaba.csp.sentinel.slots.block.BlockException; | ||||
import com.alibaba.csp.sentinel.spi.SpiOrder; | |||||
import com.alibaba.csp.sentinel.util.AssertUtil; | import com.alibaba.csp.sentinel.util.AssertUtil; | ||||
import com.alibaba.csp.sentinel.util.function.Function; | import com.alibaba.csp.sentinel.util.function.Function; | ||||
import java.util.Collection; | |||||
import java.util.List; | |||||
import java.util.Map; | |||||
/** | /** | ||||
* <p> | * <p> | ||||
* Combined the runtime statistics collected from the previous | * Combined the runtime statistics collected from the previous | ||||
@@ -136,6 +137,7 @@ import com.alibaba.csp.sentinel.util.function.Function; | |||||
* @author jialiang.linjl | * @author jialiang.linjl | ||||
* @author Eric Zhao | * @author Eric Zhao | ||||
*/ | */ | ||||
@SpiOrder(-2000) | |||||
public class FlowSlot extends AbstractLinkedProcessorSlot<DefaultNode> { | public class FlowSlot extends AbstractLinkedProcessorSlot<DefaultNode> { | ||||
private final FlowRuleChecker checker; | private final FlowRuleChecker checker; | ||||
@@ -30,6 +30,7 @@ import com.alibaba.csp.sentinel.slotchain.AbstractLinkedProcessorSlot; | |||||
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotChain; | import com.alibaba.csp.sentinel.slotchain.ProcessorSlotChain; | ||||
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; | import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; | ||||
import com.alibaba.csp.sentinel.slotchain.StringResourceWrapper; | import com.alibaba.csp.sentinel.slotchain.StringResourceWrapper; | ||||
import com.alibaba.csp.sentinel.spi.SpiOrder; | |||||
/** | /** | ||||
* <p> | * <p> | ||||
@@ -44,6 +45,7 @@ import com.alibaba.csp.sentinel.slotchain.StringResourceWrapper; | |||||
* | * | ||||
* @author jialiang.linjl | * @author jialiang.linjl | ||||
*/ | */ | ||||
@SpiOrder(-9000) | |||||
public class ClusterBuilderSlot extends AbstractLinkedProcessorSlot<DefaultNode> { | public class ClusterBuilderSlot extends AbstractLinkedProcessorSlot<DefaultNode> { | ||||
/** | /** | ||||
@@ -21,11 +21,13 @@ 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.BlockException; | import com.alibaba.csp.sentinel.slots.block.BlockException; | ||||
import com.alibaba.csp.sentinel.spi.SpiOrder; | |||||
/** | /** | ||||
* A {@link com.alibaba.csp.sentinel.slotchain.ProcessorSlot} that is response for logging block exceptions | * A {@link com.alibaba.csp.sentinel.slotchain.ProcessorSlot} that is response for logging block exceptions | ||||
* to provide concrete logs for troubleshooting. | * to provide concrete logs for troubleshooting. | ||||
*/ | */ | ||||
@SpiOrder(-8000) | |||||
public class LogSlot extends AbstractLinkedProcessorSlot<DefaultNode> { | public class LogSlot extends AbstractLinkedProcessorSlot<DefaultNode> { | ||||
@Override | @Override | ||||
@@ -22,6 +22,7 @@ import com.alibaba.csp.sentinel.node.DefaultNode; | |||||
import com.alibaba.csp.sentinel.node.EntranceNode; | import com.alibaba.csp.sentinel.node.EntranceNode; | ||||
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.spi.SpiOrder; | |||||
import java.util.HashMap; | import java.util.HashMap; | ||||
import java.util.Map; | import java.util.Map; | ||||
@@ -122,6 +123,7 @@ import java.util.Map; | |||||
* @see EntranceNode | * @see EntranceNode | ||||
* @see ContextUtil | * @see ContextUtil | ||||
*/ | */ | ||||
@SpiOrder(-10000) | |||||
public class NodeSelectorSlot extends AbstractLinkedProcessorSlot<Object> { | public class NodeSelectorSlot extends AbstractLinkedProcessorSlot<Object> { | ||||
/** | /** | ||||
@@ -21,6 +21,7 @@ import com.alibaba.csp.sentinel.config.SentinelConfig; | |||||
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotEntryCallback; | import com.alibaba.csp.sentinel.slotchain.ProcessorSlotEntryCallback; | ||||
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotExitCallback; | import com.alibaba.csp.sentinel.slotchain.ProcessorSlotExitCallback; | ||||
import com.alibaba.csp.sentinel.slots.block.flow.PriorityWaitException; | import com.alibaba.csp.sentinel.slots.block.flow.PriorityWaitException; | ||||
import com.alibaba.csp.sentinel.spi.SpiOrder; | |||||
import com.alibaba.csp.sentinel.util.TimeUtil; | import com.alibaba.csp.sentinel.util.TimeUtil; | ||||
import com.alibaba.csp.sentinel.Constants; | import com.alibaba.csp.sentinel.Constants; | ||||
import com.alibaba.csp.sentinel.EntryType; | import com.alibaba.csp.sentinel.EntryType; | ||||
@@ -47,6 +48,7 @@ import com.alibaba.csp.sentinel.slots.block.BlockException; | |||||
* @author jialiang.linjl | * @author jialiang.linjl | ||||
* @author Eric Zhao | * @author Eric Zhao | ||||
*/ | */ | ||||
@SpiOrder(-7000) | |||||
public class StatisticSlot extends AbstractLinkedProcessorSlot<DefaultNode> { | public class StatisticSlot extends AbstractLinkedProcessorSlot<DefaultNode> { | ||||
@Override | @Override | ||||
@@ -20,6 +20,7 @@ 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.ProcessorSlot; | import com.alibaba.csp.sentinel.slotchain.ProcessorSlot; | ||||
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; | import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; | ||||
import com.alibaba.csp.sentinel.spi.SpiOrder; | |||||
/** | /** | ||||
* A {@link ProcessorSlot} that dedicates to {@link SystemRule} checking. | * A {@link ProcessorSlot} that dedicates to {@link SystemRule} checking. | ||||
@@ -27,6 +28,7 @@ import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; | |||||
* @author jialiang.linjl | * @author jialiang.linjl | ||||
* @author leyou | * @author leyou | ||||
*/ | */ | ||||
@SpiOrder(-5000) | |||||
public class SystemSlot extends AbstractLinkedProcessorSlot<DefaultNode> { | public class SystemSlot extends AbstractLinkedProcessorSlot<DefaultNode> { | ||||
@Override | @Override | ||||
@@ -129,6 +129,7 @@ public final class SpiLoader { | |||||
} | } | ||||
/** | /** | ||||
* Load and sorted SPI instance list. | |||||
* Load the SPI instance list for provided SPI interface. | * Load the SPI instance list for provided SPI interface. | ||||
* | * | ||||
* @param clazz class of the SPI | * @param clazz class of the SPI | ||||
@@ -161,6 +162,8 @@ public final class SpiLoader { | |||||
/** | /** | ||||
* Load the sorted SPI instance list for provided SPI interface. | * Load the sorted SPI instance list for provided SPI interface. | ||||
* | * | ||||
* Note: each call return new instances. | |||||
* | |||||
* @param clazz class of the SPI | * @param clazz class of the SPI | ||||
* @param <T> SPI type | * @param <T> SPI type | ||||
* @return sorted SPI instance list | * @return sorted SPI instance list | ||||
@@ -196,6 +199,41 @@ public final class SpiLoader { | |||||
} | } | ||||
} | } | ||||
/** | |||||
* Load the sorted and different SPI instance list for provided SPI interface. | |||||
* | |||||
* Note: each call return new instances. | |||||
* | |||||
* @param clazz class of the SPI | |||||
* @param <T> SPI type | |||||
* @return sorted and different SPI instance list | |||||
* @since 1.7.2 | |||||
*/ | |||||
public static <T> List<T> loadDifferentInstanceListSorted(Class<T> clazz) { | |||||
try { | |||||
// Not use SERVICE_LOADER_MAP, to make sure the instances loaded are different. | |||||
ServiceLoader<T> serviceLoader = ServiceLoaderUtil.getServiceLoader(clazz); | |||||
List<SpiOrderWrapper<T>> orderWrappers = new ArrayList<>(); | |||||
for (T spi : serviceLoader) { | |||||
int order = SpiOrderResolver.resolveOrder(spi); | |||||
// Since SPI is lazy initialized in ServiceLoader, we use online sort algorithm here. | |||||
SpiOrderResolver.insertSorted(orderWrappers, spi, order); | |||||
RecordLog.info("[SpiLoader] Found {0} SPI: {1} with order " + order, clazz.getSimpleName(), | |||||
spi.getClass().getCanonicalName()); | |||||
} | |||||
List<T> list = new ArrayList<>(); | |||||
for (int i = 0; i < orderWrappers.size(); i++) { | |||||
list.add(i, orderWrappers.get(i).spi); | |||||
} | |||||
return list; | |||||
} catch (Throwable t) { | |||||
RecordLog.warn("[SpiLoader] ERROR: loadDifferentInstanceListSorted failed", t); | |||||
t.printStackTrace(); | |||||
return new ArrayList<>(); | |||||
} | |||||
} | |||||
private static class SpiOrderResolver { | private static class SpiOrderResolver { | ||||
private static <T> void insertSorted(List<SpiOrderWrapper<T>> list, T spi, int order) { | private static <T> void insertSorted(List<SpiOrderWrapper<T>> list, T spi, int order) { | ||||
int idx = 0; | int idx = 0; | ||||
@@ -0,0 +1,9 @@ | |||||
# Sentinel default ProcessorSlots | |||||
com.alibaba.csp.sentinel.slots.nodeselector.NodeSelectorSlot | |||||
com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot | |||||
com.alibaba.csp.sentinel.slots.logger.LogSlot | |||||
com.alibaba.csp.sentinel.slots.statistic.StatisticSlot | |||||
com.alibaba.csp.sentinel.slots.system.SystemSlot | |||||
com.alibaba.csp.sentinel.slots.block.authority.AuthoritySlot | |||||
com.alibaba.csp.sentinel.slots.block.flow.FlowSlot | |||||
com.alibaba.csp.sentinel.slots.block.degrade.DegradeSlot |
@@ -0,0 +1,89 @@ | |||||
/* | |||||
* 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.slots; | |||||
import com.alibaba.csp.sentinel.slotchain.AbstractLinkedProcessorSlot; | |||||
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotChain; | |||||
import com.alibaba.csp.sentinel.slots.block.authority.AuthoritySlot; | |||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeSlot; | |||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowSlot; | |||||
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot; | |||||
import com.alibaba.csp.sentinel.slots.logger.LogSlot; | |||||
import com.alibaba.csp.sentinel.slots.nodeselector.NodeSelectorSlot; | |||||
import com.alibaba.csp.sentinel.slots.statistic.StatisticSlot; | |||||
import com.alibaba.csp.sentinel.slots.system.SystemSlot; | |||||
import org.junit.Test; | |||||
import static org.junit.Assert.*; | |||||
/** | |||||
* Test cases for {@link DefaultSlotChainBuilder}. | |||||
* | |||||
* @author cdfive | |||||
*/ | |||||
public class DefaultSlotChainBuilderTest { | |||||
@Test | |||||
public void testBuild() { | |||||
DefaultSlotChainBuilder builder = new DefaultSlotChainBuilder(); | |||||
ProcessorSlotChain slotChain = builder.build(); | |||||
assertNotNull(slotChain); | |||||
// Verify the order of slot | |||||
AbstractLinkedProcessorSlot<?> next = slotChain.getNext(); | |||||
assertTrue(next instanceof NodeSelectorSlot); | |||||
// Store the first NodeSelectorSlot instance | |||||
NodeSelectorSlot nodeSelectorSlot = (NodeSelectorSlot) next; | |||||
next = next.getNext(); | |||||
assertTrue(next instanceof ClusterBuilderSlot); | |||||
next = next.getNext(); | |||||
assertTrue(next instanceof LogSlot); | |||||
next = next.getNext(); | |||||
assertTrue(next instanceof StatisticSlot); | |||||
next = next.getNext(); | |||||
assertTrue(next instanceof AuthoritySlot); | |||||
next = next.getNext(); | |||||
assertTrue(next instanceof SystemSlot); | |||||
next = next.getNext(); | |||||
assertTrue(next instanceof FlowSlot); | |||||
next = next.getNext(); | |||||
assertTrue(next instanceof DegradeSlot); | |||||
next = next.getNext(); | |||||
assertNull(next); | |||||
// Build again to verify different instances | |||||
ProcessorSlotChain slotChain2 = builder.build(); | |||||
assertNotNull(slotChain2); | |||||
// Verify the two ProcessorSlotChain instances are different | |||||
assertNotSame(slotChain, slotChain2); | |||||
next = slotChain2.getNext(); | |||||
assertTrue(next instanceof NodeSelectorSlot); | |||||
// Store the second NodeSelectorSlot instance | |||||
NodeSelectorSlot nodeSelectorSlot2 = (NodeSelectorSlot) next; | |||||
// Verify the two NodeSelectorSlot instances are different | |||||
assertNotSame(nodeSelectorSlot, nodeSelectorSlot2); | |||||
} | |||||
} |
@@ -0,0 +1,146 @@ | |||||
/* | |||||
* 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.util; | |||||
import com.alibaba.csp.sentinel.slotchain.ProcessorSlot; | |||||
import com.alibaba.csp.sentinel.slotchain.SlotChainBuilder; | |||||
import com.alibaba.csp.sentinel.slots.DefaultSlotChainBuilder; | |||||
import com.alibaba.csp.sentinel.slots.block.authority.AuthoritySlot; | |||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeSlot; | |||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowSlot; | |||||
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot; | |||||
import com.alibaba.csp.sentinel.slots.logger.LogSlot; | |||||
import com.alibaba.csp.sentinel.slots.nodeselector.NodeSelectorSlot; | |||||
import com.alibaba.csp.sentinel.slots.statistic.StatisticSlot; | |||||
import com.alibaba.csp.sentinel.slots.system.SystemSlot; | |||||
import org.junit.Test; | |||||
import java.util.List; | |||||
import static org.junit.Assert.*; | |||||
/** | |||||
* Test cases for {@link SpiLoader}. | |||||
* | |||||
* @author cdfive | |||||
*/ | |||||
public class SpiLoaderTest { | |||||
@Test | |||||
public void testLoadFirstInstance() { | |||||
ProcessorSlot processorSlot = SpiLoader.loadFirstInstance(ProcessorSlot.class); | |||||
assertNotNull(processorSlot); | |||||
SlotChainBuilder slotChainBuilder = SpiLoader.loadFirstInstance(SlotChainBuilder.class); | |||||
assertNotNull(slotChainBuilder); | |||||
assertTrue(slotChainBuilder instanceof DefaultSlotChainBuilder); | |||||
} | |||||
@Test | |||||
public void testLoadHighestPriorityInstance() { | |||||
ProcessorSlot processorSlot = SpiLoader.loadHighestPriorityInstance(ProcessorSlot.class); | |||||
assertNotNull(processorSlot); | |||||
// NodeSelectorSlot is highest order with @SpiOrder(-9000), among all slots | |||||
assertTrue(processorSlot instanceof NodeSelectorSlot); | |||||
} | |||||
@Test | |||||
public void testLoadInstanceList() { | |||||
List<ProcessorSlot> slots = SpiLoader.loadInstanceList(ProcessorSlot.class); | |||||
assertNotNull(slots); | |||||
// Total 8 default slot in sentinel-core | |||||
assertEquals(8, slots.size()); | |||||
// Store the first slot of slots | |||||
ProcessorSlot firstSlot = slots.get(0); | |||||
// Call loadInstanceList again | |||||
List<ProcessorSlot> slots2 = SpiLoader.loadInstanceList(ProcessorSlot.class); | |||||
assertNotSame(slots, slots2); | |||||
// Store the first slot of slots | |||||
ProcessorSlot firstSlot2 = slots2.get(0); | |||||
// As SERVICE_LOADER_MAP in SpiLoader cached the instance, so they're same instances | |||||
assertSame(firstSlot, firstSlot2); | |||||
} | |||||
@Test | |||||
public void testLoadInstanceListSorted() { | |||||
List<ProcessorSlot> sortedSlots = SpiLoader.loadInstanceListSorted(ProcessorSlot.class); | |||||
assertNotNull(sortedSlots); | |||||
// Total 8 default slot in sentinel-core | |||||
assertEquals(8, sortedSlots.size()); | |||||
// Verify the order of slot | |||||
int index = 0; | |||||
assertTrue(sortedSlots.get(index++) instanceof NodeSelectorSlot); | |||||
assertTrue(sortedSlots.get(index++) instanceof ClusterBuilderSlot); | |||||
assertTrue(sortedSlots.get(index++) instanceof LogSlot); | |||||
assertTrue(sortedSlots.get(index++) instanceof StatisticSlot); | |||||
assertTrue(sortedSlots.get(index++) instanceof AuthoritySlot); | |||||
assertTrue(sortedSlots.get(index++) instanceof SystemSlot); | |||||
assertTrue(sortedSlots.get(index++) instanceof FlowSlot); | |||||
assertTrue(sortedSlots.get(index++) instanceof DegradeSlot); | |||||
// Verify each call return different instances | |||||
List<ProcessorSlot> sortedSlots2 = SpiLoader.loadInstanceListSorted(ProcessorSlot.class); | |||||
assertNotSame(sortedSlots, sortedSlots2); | |||||
assertEquals(sortedSlots.size(), sortedSlots2.size()); | |||||
for (int i = 0; i < sortedSlots.size(); i++) { | |||||
ProcessorSlot slot = sortedSlots.get(i); | |||||
ProcessorSlot slot2 = sortedSlots2.get(i); | |||||
assertEquals(slot.getClass(), slot2.getClass()); | |||||
} | |||||
} | |||||
@Test | |||||
public void testLoadDifferentInstanceListSorted() { | |||||
List<ProcessorSlot> sortedSlots = SpiLoader.loadInstanceListSorted(ProcessorSlot.class); | |||||
assertNotNull(sortedSlots); | |||||
// Total 8 default slot in sentinel-core | |||||
assertEquals(8, sortedSlots.size()); | |||||
// Verify the order of slot | |||||
int index = 0; | |||||
assertTrue(sortedSlots.get(index++) instanceof NodeSelectorSlot); | |||||
assertTrue(sortedSlots.get(index++) instanceof ClusterBuilderSlot); | |||||
assertTrue(sortedSlots.get(index++) instanceof LogSlot); | |||||
assertTrue(sortedSlots.get(index++) instanceof StatisticSlot); | |||||
assertTrue(sortedSlots.get(index++) instanceof AuthoritySlot); | |||||
assertTrue(sortedSlots.get(index++) instanceof SystemSlot); | |||||
assertTrue(sortedSlots.get(index++) instanceof FlowSlot); | |||||
assertTrue(sortedSlots.get(index++) instanceof DegradeSlot); | |||||
// Verify each call return different instances | |||||
List<ProcessorSlot> sortedSlots2 = SpiLoader.loadDifferentInstanceListSorted(ProcessorSlot.class); | |||||
assertNotSame(sortedSlots, sortedSlots2); | |||||
assertEquals(sortedSlots.size(), sortedSlots2.size()); | |||||
for (int i = 0; i < sortedSlots.size(); i++) { | |||||
ProcessorSlot slot = sortedSlots.get(i); | |||||
ProcessorSlot slot2 = sortedSlots2.get(i); | |||||
assertEquals(slot.getClass(), slot2.getClass()); | |||||
// Verify the instances are different | |||||
assertNotSame(slot, slot2); | |||||
assertNotEquals(slot, slot2); | |||||
} | |||||
} | |||||
} |
@@ -15,38 +15,18 @@ | |||||
*/ | */ | ||||
package com.alibaba.csp.sentinel.slots; | package com.alibaba.csp.sentinel.slots; | ||||
import com.alibaba.csp.sentinel.slotchain.DefaultProcessorSlotChain; | |||||
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotChain; | |||||
import com.alibaba.csp.sentinel.slotchain.SlotChainBuilder; | |||||
import com.alibaba.csp.sentinel.slots.block.authority.AuthoritySlot; | |||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeSlot; | |||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowSlot; | |||||
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowSlot; | import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowSlot; | ||||
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot; | |||||
import com.alibaba.csp.sentinel.slots.logger.LogSlot; | |||||
import com.alibaba.csp.sentinel.slots.nodeselector.NodeSelectorSlot; | |||||
import com.alibaba.csp.sentinel.slots.statistic.StatisticSlot; | |||||
import com.alibaba.csp.sentinel.slots.system.SystemSlot; | |||||
/** | /** | ||||
* @author Eric Zhao | * @author Eric Zhao | ||||
* @since 0.2.0 | * @since 0.2.0 | ||||
* | |||||
* @deprecated since 1.7.2, we can use @SpiOrder(-3000) to adjust the order of {@link ParamFlowSlot}, | |||||
* this class is reserved for compatibility with older versions. | |||||
* @see ParamFlowSlot | |||||
* @see DefaultSlotChainBuilder | |||||
*/ | */ | ||||
public class HotParamSlotChainBuilder implements SlotChainBuilder { | |||||
@Override | |||||
public ProcessorSlotChain build() { | |||||
ProcessorSlotChain chain = new DefaultProcessorSlotChain(); | |||||
chain.addLast(new NodeSelectorSlot()); | |||||
chain.addLast(new ClusterBuilderSlot()); | |||||
chain.addLast(new LogSlot()); | |||||
chain.addLast(new StatisticSlot()); | |||||
chain.addLast(new AuthoritySlot()); | |||||
chain.addLast(new SystemSlot()); | |||||
chain.addLast(new ParamFlowSlot()); | |||||
chain.addLast(new FlowSlot()); | |||||
chain.addLast(new DegradeSlot()); | |||||
@Deprecated | |||||
public class HotParamSlotChainBuilder extends DefaultSlotChainBuilder { | |||||
return chain; | |||||
} | |||||
} | } |
@@ -15,13 +15,14 @@ | |||||
*/ | */ | ||||
package com.alibaba.csp.sentinel.slots.block.flow.param; | package com.alibaba.csp.sentinel.slots.block.flow.param; | ||||
import java.util.List; | |||||
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.BlockException; | import com.alibaba.csp.sentinel.slots.block.BlockException; | ||||
import com.alibaba.csp.sentinel.spi.SpiOrder; | |||||
import java.util.List; | |||||
/** | /** | ||||
* A processor slot that is responsible for flow control by frequent ("hot spot") parameters. | * A processor slot that is responsible for flow control by frequent ("hot spot") parameters. | ||||
@@ -30,6 +31,7 @@ import com.alibaba.csp.sentinel.slots.block.BlockException; | |||||
* @author Eric Zhao | * @author Eric Zhao | ||||
* @since 0.2.0 | * @since 0.2.0 | ||||
*/ | */ | ||||
@SpiOrder(-3000) | |||||
public class ParamFlowSlot extends AbstractLinkedProcessorSlot<DefaultNode> { | public class ParamFlowSlot extends AbstractLinkedProcessorSlot<DefaultNode> { | ||||
@Override | @Override | ||||
@@ -0,0 +1 @@ | |||||
com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowSlot |
@@ -1 +0,0 @@ | |||||
com.alibaba.csp.sentinel.slots.HotParamSlotChainBuilder |