Skip to content

Commit

Permalink
Merge from master and use @SpiOrder and SpiLoader.loadInstanceListSor…
Browse files Browse the repository at this point in the history
…ted(Class<T> clazz) method.
  • Loading branch information
cdfive committed Apr 20, 2019
1 parent 030ec23 commit ee1b5ab
Show file tree
Hide file tree
Showing 17 changed files with 230 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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}.
Expand All @@ -38,16 +36,17 @@ 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 SystemSlot());
chain.addLast(new AuthoritySlot());
chain.addLast(new FlowSlot());
chain.addLast(new DegradeSlot());

List<ProcessorSlot> sortedSlotList = SpiLoader.loadInstanceListSorted(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;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@
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.
*
* @author leyou
* @author Eric Zhao
*/
@SpiOrder(-3000)
public class AuthoritySlot extends AbstractLinkedProcessorSlot<DefaultNode> {

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
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;

/**
* <p>
Expand Down Expand Up @@ -133,6 +134,7 @@
* @author jialiang.linjl
* @author Eric Zhao
*/
@SpiOrder(-2000)
public class FlowSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
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>
Expand All @@ -44,6 +45,7 @@
*
* @author jialiang.linjl
*/
@SpiOrder(-8000)
public class ClusterBuilderSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@
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(-7000)
public class LogSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
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;

/**
* </p>
Expand Down Expand Up @@ -122,6 +123,7 @@
* @see EntranceNode
* @see ContextUtil
*/
@SpiOrder(-9000)
public class NodeSelectorSlot extends AbstractLinkedProcessorSlot<Object> {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
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;
Expand All @@ -46,6 +47,7 @@
* @author jialiang.linjl
* @author Eric Zhao
*/
@SpiOrder(-6000)
public class StatisticSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@
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.
*
* @author jialiang.linjl
* @author leyou
*/
@SpiOrder(-4000)
public class SystemSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ public static <T> T loadHighestPriorityInstance(Class<T> clazz) {
}

/**
* Load and sorted SPI instance list.
* Load and sorted SPI instance list
*
* Note: each call return new instances.
*
* @param clazz class of the SPI
* @param <T> SPI type
Expand All @@ -101,13 +103,8 @@ public static <T> T loadHighestPriorityInstance(Class<T> clazz) {
*/
public static <T> List<T> loadInstanceListSorted(Class<T> clazz) {
try {
String key = clazz.getName();
// Not thread-safe, as it's expected to be resolved in a thread-safe context.
ServiceLoader<T> serviceLoader = SERVICE_LOADER_MAP.get(key);
if (serviceLoader == null) {
serviceLoader = ServiceLoader.load(clazz);
SERVICE_LOADER_MAP.put(key, serviceLoader);
}
// Call ServiceLoader.load(clazz) to get new instance
ServiceLoader<T> serviceLoader = ServiceLoader.load(clazz);

List<SpiOrderWrapper<T>> orderWrappers = new ArrayList<>();
for (T spi : serviceLoader) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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 SystemSlot);

next = next.getNext();
assertTrue(next instanceof AuthoritySlot);

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);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* 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 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 SystemSlot);
assertTrue(sortedSlots.get(index++) instanceof AuthoritySlot);
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);
assertNotSame(slot, slot2);
assertNotEquals(slot, slot2);
assertEquals(slot.getClass(), slot2.getClass());
}
}
}
Loading

0 comments on commit ee1b5ab

Please sign in to comment.