Browse Source

Set default log level of JDK logging to INFO and polish code of SpiLoader (#1365)

* Improve log info in SpiLoader, improve comment and test case
* Use error level in catch block, init ArrayList with capacity and improve add item to list
master
cdfive GitHub 4 years ago
parent
commit
e1435974c6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 61 additions and 28 deletions
  1. +3
    -1
      sentinel-core/src/main/java/com/alibaba/csp/sentinel/log/jul/BaseJulLogger.java
  2. +1
    -1
      sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/DefaultSlotChainBuilder.java
  3. +34
    -20
      sentinel-core/src/main/java/com/alibaba/csp/sentinel/util/SpiLoader.java
  4. +23
    -6
      sentinel-core/src/test/java/com/alibaba/csp/sentinel/util/SpiLoaderTest.java

+ 3
- 1
sentinel-core/src/main/java/com/alibaba/csp/sentinel/log/jul/BaseJulLogger.java View File

@@ -90,7 +90,9 @@ public class BaseJulLogger {
if (handler != null) { if (handler != null) {
disableOtherHandlers(heliumRecordLog, handler); disableOtherHandlers(heliumRecordLog, handler);
} }
heliumRecordLog.setLevel(Level.ALL);

// Set log level to INFO by default
heliumRecordLog.setLevel(Level.INFO);
return handler; return handler;
} }




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

@@ -38,7 +38,7 @@ public class DefaultSlotChainBuilder implements SlotChainBuilder {
ProcessorSlotChain chain = new DefaultProcessorSlotChain(); ProcessorSlotChain chain = new DefaultProcessorSlotChain();


// Note: the instances of ProcessorSlot should be different, since they are not stateless. // Note: the instances of ProcessorSlot should be different, since they are not stateless.
List<ProcessorSlot> sortedSlotList = SpiLoader.loadDifferentInstanceListSorted(ProcessorSlot.class);
List<ProcessorSlot> sortedSlotList = SpiLoader.loadPrototypeInstanceListSorted(ProcessorSlot.class);
for (ProcessorSlot slot : sortedSlotList) { for (ProcessorSlot slot : sortedSlotList) {
if (!(slot instanceof AbstractLinkedProcessorSlot)) { if (!(slot instanceof AbstractLinkedProcessorSlot)) {
RecordLog.warn("The ProcessorSlot(" + slot.getClass().getCanonicalName() + ") is not an instance of AbstractLinkedProcessorSlot, can't be added into ProcessorSlotChain"); RecordLog.warn("The ProcessorSlot(" + slot.getClass().getCanonicalName() + ") is not an instance of AbstractLinkedProcessorSlot, can't be added into ProcessorSlotChain");


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

@@ -34,6 +34,14 @@ public final class SpiLoader {


private static final Map<String, ServiceLoader> SERVICE_LOADER_MAP = new ConcurrentHashMap<String, ServiceLoader>(); private static final Map<String, ServiceLoader> SERVICE_LOADER_MAP = new ConcurrentHashMap<String, ServiceLoader>();


/**
* Load the first-found specific SPI instance
*
* @param clazz class of the SPI interface
* @param <T> SPI type
* @return the first specific SPI instance if exists, or else return null
* @since 1.7.0
*/
public static <T> T loadFirstInstance(Class<T> clazz) { public static <T> T loadFirstInstance(Class<T> clazz) {
AssertUtil.notNull(clazz, "SPI class cannot be null"); AssertUtil.notNull(clazz, "SPI class cannot be null");
try { try {
@@ -52,7 +60,7 @@ public final class SpiLoader {
return null; return null;
} }
} catch (Throwable t) { } catch (Throwable t) {
RecordLog.warn("[SpiLoader] ERROR: loadFirstInstance failed", t);
RecordLog.error("[SpiLoader] ERROR: loadFirstInstance failed", t);
t.printStackTrace(); t.printStackTrace();
return null; return null;
} }
@@ -87,7 +95,7 @@ public final class SpiLoader {
} }
return defaultClass.newInstance(); return defaultClass.newInstance();
} catch (Throwable t) { } catch (Throwable t) {
RecordLog.warn("[SpiLoader] ERROR: loadFirstInstanceOrDefault failed", t);
RecordLog.error("[SpiLoader] ERROR: loadFirstInstanceOrDefault failed", t);
t.printStackTrace(); t.printStackTrace();
return null; return null;
} }
@@ -96,6 +104,8 @@ public final class SpiLoader {
/** /**
* Load the SPI instance with highest priority. * Load the SPI instance with highest priority.
* *
* Note: each call return same instances.
*
* @param clazz class of the SPI * @param clazz class of the SPI
* @param <T> SPI type * @param <T> SPI type
* @return the SPI instance with highest priority if exists, or else false * @return the SPI instance with highest priority if exists, or else false
@@ -114,15 +124,15 @@ public final class SpiLoader {
SpiOrderWrapper<T> w = null; SpiOrderWrapper<T> w = null;
for (T spi : serviceLoader) { for (T spi : serviceLoader) {
int order = SpiOrderResolver.resolveOrder(spi); int order = SpiOrderResolver.resolveOrder(spi);
RecordLog.info("[SpiLoader] Found {} SPI: {} with order " + order, clazz.getSimpleName(),
spi.getClass().getCanonicalName());
RecordLog.info("[SpiLoader] Found {} SPI: {} with order {}", clazz.getSimpleName(),
spi.getClass().getCanonicalName(), order);
if (w == null || order < w.order) { if (w == null || order < w.order) {
w = new SpiOrderWrapper<>(order, spi); w = new SpiOrderWrapper<>(order, spi);
} }
} }
return w == null ? null : w.spi; return w == null ? null : w.spi;
} catch (Throwable t) { } catch (Throwable t) {
RecordLog.warn("[SpiLoader] ERROR: loadHighestPriorityInstance failed", t);
RecordLog.error("[SpiLoader] ERROR: loadHighestPriorityInstance failed", t);
t.printStackTrace(); t.printStackTrace();
return null; return null;
} }
@@ -132,6 +142,8 @@ public final class SpiLoader {
* Load and sorted SPI instance list. * Load and sorted SPI instance list.
* Load the SPI instance list for provided SPI interface. * Load the SPI instance list for provided SPI interface.
* *
* Note: each call return same 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
@@ -149,11 +161,13 @@ public final class SpiLoader {


List<T> list = new ArrayList<>(); List<T> list = new ArrayList<>();
for (T spi : serviceLoader) { for (T spi : serviceLoader) {
RecordLog.info("[SpiLoader] Found {} SPI: {}", clazz.getSimpleName(),
spi.getClass().getCanonicalName());
list.add(spi); list.add(spi);
} }
return list; return list;
} catch (Throwable t) { } catch (Throwable t) {
RecordLog.warn("[SpiLoader] ERROR: loadInstanceListSorted failed", t);
RecordLog.error("[SpiLoader] ERROR: loadInstanceList failed", t);
t.printStackTrace(); t.printStackTrace();
return new ArrayList<>(); return new ArrayList<>();
} }
@@ -162,7 +176,7 @@ 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.
* Note: each call return same instances.
* *
* @param clazz class of the SPI * @param clazz class of the SPI
* @param <T> SPI type * @param <T> SPI type
@@ -184,32 +198,32 @@ public final class SpiLoader {
int order = SpiOrderResolver.resolveOrder(spi); int order = SpiOrderResolver.resolveOrder(spi);
// Since SPI is lazy initialized in ServiceLoader, we use online sort algorithm here. // Since SPI is lazy initialized in ServiceLoader, we use online sort algorithm here.
SpiOrderResolver.insertSorted(orderWrappers, spi, order); SpiOrderResolver.insertSorted(orderWrappers, spi, order);
RecordLog.info("[SpiLoader] Found {} SPI: {} with order " + order, clazz.getSimpleName(),
spi.getClass().getCanonicalName());
RecordLog.info("[SpiLoader] Found {} SPI: {} with order {}", clazz.getSimpleName(),
spi.getClass().getCanonicalName(), order);
} }
List<T> list = new ArrayList<>();
List<T> list = new ArrayList<>(orderWrappers.size());
for (int i = 0; i < orderWrappers.size(); i++) { for (int i = 0; i < orderWrappers.size(); i++) {
list.add(i, orderWrappers.get(i).spi);
list.add(orderWrappers.get(i).spi);
} }
return list; return list;
} catch (Throwable t) { } catch (Throwable t) {
RecordLog.warn("[SpiLoader] ERROR: loadInstanceListSorted failed", t);
RecordLog.error("[SpiLoader] ERROR: loadInstanceListSorted failed", t);
t.printStackTrace(); t.printStackTrace();
return new ArrayList<>(); return new ArrayList<>();
} }
} }


/** /**
* Load the sorted and different SPI instance list for provided SPI interface.
* Load the sorted and prototype SPI instance list for provided SPI interface.
* *
* Note: each call return new instances.
* Note: each call return different instances, i.e. prototype instance, not singleton instance.
* *
* @param clazz class of the SPI * @param clazz class of the SPI
* @param <T> SPI type * @param <T> SPI type
* @return sorted and different SPI instance list * @return sorted and different SPI instance list
* @since 1.7.2 * @since 1.7.2
*/ */
public static <T> List<T> loadDifferentInstanceListSorted(Class<T> clazz) {
public static <T> List<T> loadPrototypeInstanceListSorted(Class<T> clazz) {
try { try {
// Not use SERVICE_LOADER_MAP, to make sure the instances loaded are different. // Not use SERVICE_LOADER_MAP, to make sure the instances loaded are different.
ServiceLoader<T> serviceLoader = ServiceLoaderUtil.getServiceLoader(clazz); ServiceLoader<T> serviceLoader = ServiceLoaderUtil.getServiceLoader(clazz);
@@ -219,16 +233,16 @@ public final class SpiLoader {
int order = SpiOrderResolver.resolveOrder(spi); int order = SpiOrderResolver.resolveOrder(spi);
// Since SPI is lazy initialized in ServiceLoader, we use online sort algorithm here. // Since SPI is lazy initialized in ServiceLoader, we use online sort algorithm here.
SpiOrderResolver.insertSorted(orderWrappers, spi, order); SpiOrderResolver.insertSorted(orderWrappers, spi, order);
RecordLog.info("[SpiLoader] Found {0} SPI: {1} with order " + order, clazz.getSimpleName(),
spi.getClass().getCanonicalName());
RecordLog.debug("[SpiLoader] Found {} SPI: {} with order {}", clazz.getSimpleName(),
spi.getClass().getCanonicalName(), order);
} }
List<T> list = new ArrayList<>();
List<T> list = new ArrayList<>(orderWrappers.size());
for (int i = 0; i < orderWrappers.size(); i++) { for (int i = 0; i < orderWrappers.size(); i++) {
list.add(i, orderWrappers.get(i).spi);
list.add(orderWrappers.get(i).spi);
} }
return list; return list;
} catch (Throwable t) { } catch (Throwable t) {
RecordLog.warn("[SpiLoader] ERROR: loadDifferentInstanceListSorted failed", t);
RecordLog.error("[SpiLoader] ERROR: loadPrototypeInstanceListSorted failed", t);
t.printStackTrace(); t.printStackTrace();
return new ArrayList<>(); return new ArrayList<>();
} }


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

@@ -44,9 +44,17 @@ public class SpiLoaderTest {
ProcessorSlot processorSlot = SpiLoader.loadFirstInstance(ProcessorSlot.class); ProcessorSlot processorSlot = SpiLoader.loadFirstInstance(ProcessorSlot.class);
assertNotNull(processorSlot); assertNotNull(processorSlot);


ProcessorSlot processorSlot2 = SpiLoader.loadFirstInstance(ProcessorSlot.class);
// As SERVICE_LOADER_MAP in SpiLoader cached the instance, so they're same instances
assertSame(processorSlot, processorSlot2);

SlotChainBuilder slotChainBuilder = SpiLoader.loadFirstInstance(SlotChainBuilder.class); SlotChainBuilder slotChainBuilder = SpiLoader.loadFirstInstance(SlotChainBuilder.class);
assertNotNull(slotChainBuilder); assertNotNull(slotChainBuilder);
assertTrue(slotChainBuilder instanceof DefaultSlotChainBuilder); assertTrue(slotChainBuilder instanceof DefaultSlotChainBuilder);

SlotChainBuilder slotChainBuilder2 = SpiLoader.loadFirstInstance(SlotChainBuilder.class);
// As SERVICE_LOADER_MAP in SpiLoader cached the instance, so they're same instances
assertSame(slotChainBuilder, slotChainBuilder2);
} }


@Test @Test
@@ -54,8 +62,12 @@ public class SpiLoaderTest {
ProcessorSlot processorSlot = SpiLoader.loadHighestPriorityInstance(ProcessorSlot.class); ProcessorSlot processorSlot = SpiLoader.loadHighestPriorityInstance(ProcessorSlot.class);
assertNotNull(processorSlot); assertNotNull(processorSlot);


// NodeSelectorSlot is highest order with @SpiOrder(-9000), among all slots
// NodeSelectorSlot is highest order with @SpiOrder(-10000), among all slots
assertTrue(processorSlot instanceof NodeSelectorSlot); assertTrue(processorSlot instanceof NodeSelectorSlot);

ProcessorSlot processorSlot2 = SpiLoader.loadHighestPriorityInstance(ProcessorSlot.class);
// As SERVICE_LOADER_MAP in SpiLoader cached the instance, so they're same instances
assertSame(processorSlot, processorSlot2);
} }


@Test @Test
@@ -66,14 +78,15 @@ public class SpiLoaderTest {
// Total 8 default slot in sentinel-core // Total 8 default slot in sentinel-core
assertEquals(8, slots.size()); assertEquals(8, slots.size());


// Store the first slot of slots
// Get the first slot of slots
ProcessorSlot firstSlot = slots.get(0); ProcessorSlot firstSlot = slots.get(0);


// Call loadInstanceList again // Call loadInstanceList again
List<ProcessorSlot> slots2 = SpiLoader.loadInstanceList(ProcessorSlot.class); List<ProcessorSlot> slots2 = SpiLoader.loadInstanceList(ProcessorSlot.class);
// Note: the return list are different, and the item instances in list are same
assertNotSame(slots, slots2); assertNotSame(slots, slots2);


// Store the first slot of slots
// Get the first slot of slots2
ProcessorSlot firstSlot2 = slots2.get(0); ProcessorSlot firstSlot2 = slots2.get(0);


// As SERVICE_LOADER_MAP in SpiLoader cached the instance, so they're same instances // As SERVICE_LOADER_MAP in SpiLoader cached the instance, so they're same instances
@@ -100,6 +113,7 @@ public class SpiLoaderTest {
assertTrue(sortedSlots.get(index++) instanceof DegradeSlot); assertTrue(sortedSlots.get(index++) instanceof DegradeSlot);


// Verify each call return different instances // Verify each call return different instances
// Note: the return list are different, and the item instances in list are same
List<ProcessorSlot> sortedSlots2 = SpiLoader.loadInstanceListSorted(ProcessorSlot.class); List<ProcessorSlot> sortedSlots2 = SpiLoader.loadInstanceListSorted(ProcessorSlot.class);
assertNotSame(sortedSlots, sortedSlots2); assertNotSame(sortedSlots, sortedSlots2);
assertEquals(sortedSlots.size(), sortedSlots2.size()); assertEquals(sortedSlots.size(), sortedSlots2.size());
@@ -107,11 +121,14 @@ public class SpiLoaderTest {
ProcessorSlot slot = sortedSlots.get(i); ProcessorSlot slot = sortedSlots.get(i);
ProcessorSlot slot2 = sortedSlots2.get(i); ProcessorSlot slot2 = sortedSlots2.get(i);
assertEquals(slot.getClass(), slot2.getClass()); assertEquals(slot.getClass(), slot2.getClass());

// As SERVICE_LOADER_MAP in SpiLoader cached the instance, so they're same instances
assertSame(slot, slot2);
} }
} }


@Test @Test
public void testLoadDifferentInstanceListSorted() {
public void testLoadPrototypeInstanceListSorted() {
List<ProcessorSlot> sortedSlots = SpiLoader.loadInstanceListSorted(ProcessorSlot.class); List<ProcessorSlot> sortedSlots = SpiLoader.loadInstanceListSorted(ProcessorSlot.class);
assertNotNull(sortedSlots); assertNotNull(sortedSlots);


@@ -129,8 +146,8 @@ public class SpiLoaderTest {
assertTrue(sortedSlots.get(index++) instanceof FlowSlot); assertTrue(sortedSlots.get(index++) instanceof FlowSlot);
assertTrue(sortedSlots.get(index++) instanceof DegradeSlot); assertTrue(sortedSlots.get(index++) instanceof DegradeSlot);


// Verify each call return different instances
List<ProcessorSlot> sortedSlots2 = SpiLoader.loadDifferentInstanceListSorted(ProcessorSlot.class);
// Verify each call return new instances
List<ProcessorSlot> sortedSlots2 = SpiLoader.loadPrototypeInstanceListSorted(ProcessorSlot.class);
assertNotSame(sortedSlots, sortedSlots2); assertNotSame(sortedSlots, sortedSlots2);
assertEquals(sortedSlots.size(), sortedSlots2.size()); assertEquals(sortedSlots.size(), sortedSlots2.size());
for (int i = 0; i < sortedSlots.size(); i++) { for (int i = 0; i < sortedSlots.size(); i++) {


Loading…
Cancel
Save