Browse Source

refactor: Make the ProcessorSlot itself as SPI and deprecate legacy slot chain builder (#411)

* 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 @Deprecated
master
cdfive GitHub 4 years ago
parent
commit
be4d058bf8
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 342 additions and 85 deletions
  1. +2
    -0
      sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/common/slot/GatewayFlowSlot.java
  2. +8
    -33
      sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/common/slot/GatewaySlotChainBuilder.java
  3. +1
    -0
      sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.ProcessorSlot
  4. +0
    -1
      sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.SlotChainBuilder
  5. +17
    -17
      sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/DefaultSlotChainBuilder.java
  6. +2
    -0
      sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/authority/AuthoritySlot.java
  7. +2
    -0
      sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeSlot.java
  8. +6
    -4
      sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/FlowSlot.java
  9. +2
    -0
      sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/clusterbuilder/ClusterBuilderSlot.java
  10. +2
    -0
      sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/logger/LogSlot.java
  11. +2
    -0
      sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/nodeselector/NodeSelectorSlot.java
  12. +2
    -0
      sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/statistic/StatisticSlot.java
  13. +2
    -0
      sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/system/SystemSlot.java
  14. +38
    -0
      sentinel-core/src/main/java/com/alibaba/csp/sentinel/util/SpiLoader.java
  15. +9
    -0
      sentinel-core/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.ProcessorSlot
  16. +89
    -0
      sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/DefaultSlotChainBuilderTest.java
  17. +146
    -0
      sentinel-core/src/test/java/com/alibaba/csp/sentinel/util/SpiLoaderTest.java
  18. +7
    -27
      sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/HotParamSlotChainBuilder.java
  19. +4
    -2
      sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowSlot.java
  20. +1
    -0
      sentinel-extension/sentinel-parameter-flow-control/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.ProcessorSlot
  21. +0
    -1
      sentinel-extension/sentinel-parameter-flow-control/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.SlotChainBuilder

+ 2
- 0
sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/common/slot/GatewayFlowSlot.java View File

@@ -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.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParameterMetricStorage;
import com.alibaba.csp.sentinel.spi.SpiOrder;

/**
* @author Eric Zhao
* @since 1.6.1
*/
@SpiOrder(-4000)
public class GatewayFlowSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

@Override


+ 8
- 33
sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/common/slot/GatewaySlotChainBuilder.java View File

@@ -15,43 +15,18 @@
*/
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
* @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;
}
}

+ 1
- 0
sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.ProcessorSlot View File

@@ -0,0 +1 @@
com.alibaba.csp.sentinel.adapter.gateway.common.slot.GatewayFlowSlot

+ 0
- 1
sentinel-adapter/sentinel-api-gateway-adapter-common/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.SlotChainBuilder View File

@@ -1 +0,0 @@
com.alibaba.csp.sentinel.adapter.gateway.common.slot.GatewaySlotChainBuilder

+ 17
- 17
sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/DefaultSlotChainBuilder.java View File

@@ -15,17 +15,15 @@
*/
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.ProcessorSlot;
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.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}.
@@ -38,16 +36,18 @@ public class DefaultSlotChainBuilder 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 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;
}

}

+ 2
- 0
sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/authority/AuthoritySlot.java View File

@@ -23,6 +23,7 @@ import com.alibaba.csp.sentinel.node.DefaultNode;
import com.alibaba.csp.sentinel.slotchain.AbstractLinkedProcessorSlot;
import com.alibaba.csp.sentinel.slotchain.ProcessorSlot;
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
import com.alibaba.csp.sentinel.spi.SpiOrder;

/**
* A {@link ProcessorSlot} that dedicates to {@link AuthorityRule} checking.
@@ -30,6 +31,7 @@ import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
* @author leyou
* @author Eric Zhao
*/
@SpiOrder(-6000)
public class AuthoritySlot extends AbstractLinkedProcessorSlot<DefaultNode> {

@Override


+ 2
- 0
sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeSlot.java View File

@@ -20,12 +20,14 @@ import com.alibaba.csp.sentinel.node.DefaultNode;
import com.alibaba.csp.sentinel.slotchain.AbstractLinkedProcessorSlot;
import com.alibaba.csp.sentinel.slotchain.ProcessorSlot;
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
import com.alibaba.csp.sentinel.spi.SpiOrder;

/**
* A {@link ProcessorSlot} dedicates to {@link DegradeRule} checking.
*
* @author leyou
*/
@SpiOrder(-1000)
public class DegradeSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

@Override


+ 6
- 4
sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/FlowSlot.java View File

@@ -15,18 +15,19 @@
*/
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.node.DefaultNode;
import com.alibaba.csp.sentinel.slotchain.AbstractLinkedProcessorSlot;
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
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.function.Function;

import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
* <p>
* Combined the runtime statistics collected from the previous
@@ -136,6 +137,7 @@ import com.alibaba.csp.sentinel.util.function.Function;
* @author jialiang.linjl
* @author Eric Zhao
*/
@SpiOrder(-2000)
public class FlowSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

private final FlowRuleChecker checker;


+ 2
- 0
sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/clusterbuilder/ClusterBuilderSlot.java View File

@@ -30,6 +30,7 @@ import com.alibaba.csp.sentinel.slotchain.AbstractLinkedProcessorSlot;
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotChain;
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
import com.alibaba.csp.sentinel.slotchain.StringResourceWrapper;
import com.alibaba.csp.sentinel.spi.SpiOrder;

/**
* <p>
@@ -44,6 +45,7 @@ import com.alibaba.csp.sentinel.slotchain.StringResourceWrapper;
*
* @author jialiang.linjl
*/
@SpiOrder(-9000)
public class ClusterBuilderSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

/**


+ 2
- 0
sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/logger/LogSlot.java View File

@@ -21,11 +21,13 @@ 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.BlockException;
import com.alibaba.csp.sentinel.spi.SpiOrder;

/**
* A {@link com.alibaba.csp.sentinel.slotchain.ProcessorSlot} that is response for logging block exceptions
* to provide concrete logs for troubleshooting.
*/
@SpiOrder(-8000)
public class LogSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

@Override


+ 2
- 0
sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/nodeselector/NodeSelectorSlot.java View File

@@ -22,6 +22,7 @@ import com.alibaba.csp.sentinel.node.DefaultNode;
import com.alibaba.csp.sentinel.node.EntranceNode;
import com.alibaba.csp.sentinel.slotchain.AbstractLinkedProcessorSlot;
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
import com.alibaba.csp.sentinel.spi.SpiOrder;

import java.util.HashMap;
import java.util.Map;
@@ -122,6 +123,7 @@ import java.util.Map;
* @see EntranceNode
* @see ContextUtil
*/
@SpiOrder(-10000)
public class NodeSelectorSlot extends AbstractLinkedProcessorSlot<Object> {

/**


+ 2
- 0
sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/statistic/StatisticSlot.java View File

@@ -21,6 +21,7 @@ import com.alibaba.csp.sentinel.config.SentinelConfig;
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotEntryCallback;
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotExitCallback;
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.Constants;
import com.alibaba.csp.sentinel.EntryType;
@@ -47,6 +48,7 @@ import com.alibaba.csp.sentinel.slots.block.BlockException;
* @author jialiang.linjl
* @author Eric Zhao
*/
@SpiOrder(-7000)
public class StatisticSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

@Override


+ 2
- 0
sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/system/SystemSlot.java View File

@@ -20,6 +20,7 @@ import com.alibaba.csp.sentinel.node.DefaultNode;
import com.alibaba.csp.sentinel.slotchain.AbstractLinkedProcessorSlot;
import com.alibaba.csp.sentinel.slotchain.ProcessorSlot;
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
import com.alibaba.csp.sentinel.spi.SpiOrder;

/**
* A {@link ProcessorSlot} that dedicates to {@link SystemRule} checking.
@@ -27,6 +28,7 @@ import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
* @author jialiang.linjl
* @author leyou
*/
@SpiOrder(-5000)
public class SystemSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

@Override


+ 38
- 0
sentinel-core/src/main/java/com/alibaba/csp/sentinel/util/SpiLoader.java View File

@@ -129,6 +129,7 @@ public final class SpiLoader {
}

/**
* Load and sorted SPI instance list.
* Load the SPI instance list for provided SPI interface.
*
* @param clazz class of the SPI
@@ -161,6 +162,8 @@ public final class SpiLoader {
/**
* Load the sorted 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 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 <T> void insertSorted(List<SpiOrderWrapper<T>> list, T spi, int order) {
int idx = 0;


+ 9
- 0
sentinel-core/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.ProcessorSlot View File

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

+ 89
- 0
sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/DefaultSlotChainBuilderTest.java View File

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

+ 146
- 0
sentinel-core/src/test/java/com/alibaba/csp/sentinel/util/SpiLoaderTest.java View File

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

+ 7
- 27
sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/HotParamSlotChainBuilder.java View File

@@ -15,38 +15,18 @@
*/
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.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
* @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;
}
}

+ 4
- 2
sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowSlot.java View File

@@ -15,13 +15,14 @@
*/
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.node.DefaultNode;
import com.alibaba.csp.sentinel.slotchain.AbstractLinkedProcessorSlot;
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
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.
@@ -30,6 +31,7 @@ import com.alibaba.csp.sentinel.slots.block.BlockException;
* @author Eric Zhao
* @since 0.2.0
*/
@SpiOrder(-3000)
public class ParamFlowSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

@Override


+ 1
- 0
sentinel-extension/sentinel-parameter-flow-control/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.ProcessorSlot View File

@@ -0,0 +1 @@
com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowSlot

+ 0
- 1
sentinel-extension/sentinel-parameter-flow-control/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.SlotChainBuilder View File

@@ -1 +0,0 @@
com.alibaba.csp.sentinel.slots.HotParamSlotChainBuilder

Loading…
Cancel
Save