Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor SpiLoader and enhance its SPI functions #1383

Merged
merged 12 commits into from
Jan 27, 2021
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import com.alibaba.csp.sentinel.property.PropertyListener;
import com.alibaba.csp.sentinel.property.SentinelProperty;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.csp.sentinel.util.SpiLoader;
import com.alibaba.csp.sentinel.spi.SpiLoader;
import com.alibaba.csp.sentinel.util.StringUtil;

/**
Expand Down Expand Up @@ -59,7 +59,7 @@ public final class GatewayApiDefinitionManager {
}

private static void initializeApiChangeObserverSpi() {
List<ApiDefinitionChangeObserver> listeners = SpiLoader.loadInstanceList(ApiDefinitionChangeObserver.class);
List<ApiDefinitionChangeObserver> listeners = SpiLoader.of(ApiDefinitionChangeObserver.class).loadInstanceList();
for (ApiDefinitionChangeObserver e : listeners) {
API_CHANGE_OBSERVERS.put(e.getClass().getCanonicalName(), e);
RecordLog.info("[GatewayApiDefinitionManager] ApiDefinitionChangeObserver added: {}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@
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;
import com.alibaba.csp.sentinel.spi.Spi;

/**
* @author Eric Zhao
* @since 1.6.1
*/
@SpiOrder(-4000)
@Spi(order = -4000)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use constant?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And some slots are stateless while others are stateful. Maybe isSingleton should be specified obviously.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little confused here, not very sure and use -4000 temporarily.
There are some constants of slot order definitions In Constants class of sentinel-core module:

/**
* Order of default processor slots
*/
public static final int ORDER_NODE_SELECTOR_SLOT = -10000;
public static final int ORDER_CLUSTER_BUILDER_SLOT = -9000;
public static final int ORDER_LOG_SLOT = -8000;
public static final int ORDER_STATISTIC_SLOT = -7000;
public static final int ORDER_AUTHORITY_SLOT = -6000;
public static final int ORDER_SYSTEM_SLOT = -5000;
// order of GatewayFlowSlot -4000
// order of ParamFlowSlot   -3000
public static final int ORDER_FLOW_SLOT = -2000;
public static final int ORDER_DEGRADE_SLOT = -1000;

If use constant, which is better?

public static final int ORDER_GATEWAY_FLOW_SLOT = -4000;
public static final int ORDER_PARAM_FLOW_SLOT = -3000;

@Spi(order = Constants.ORDER_SYSTEM_SLOT)
public class GatewayFlowSlot {
No constant for ORDER_GATEWAY_FLOW_SLOT, ORDER_PARAM_FLOW_SLOT
@Spi(order = Constants.ORDER_SYSTEM_SLOT + 1000)
public class GatewayFlowSlot {

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Constants.ORDER_SYSTEM_SLOT

Yeah whatever you want.

If you want to make it reference-able just replace it with a constant in gateway package;
If you want to express some kinds of relationship with existing slots just use relative calculation to existed constants;
If you insist on pure definition just leave it unchanged.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These three ways speak my heart. I've been struggling with this for a long time.
Now I think the third way is not very good. Maybe one or two is better.
For a selection difficulty person, could you please help to make a good choice?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These three ways speak my heart. I've been struggling with this for a long time.
Now I think the third way is not very good. Maybe one or two is better.
For a selection difficulty person, could you please help to make a good choice?

Go write a random test and make result confirmed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it! Using the first way, since it expresses the order of all default slot of sentinel clearly. Maybe the second way is a good choice for user custom slot.

public class GatewayFlowSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@
* @author Eric Zhao
* @since 1.6.1
*
* @deprecated since 1.7.2, we can use @SpiOrder(-4000) to adjust the order of {@link GatewayFlowSlot},
* @deprecated since 1.7.2, we can use @Spi(order = -4000) to adjust the order of {@link GatewayFlowSlot},
* this class is reserved for compatibility with older versions.
*
* @see GatewayFlowSlot
* @see DefaultSlotChainBuilder
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/
package com.alibaba.csp.sentinel.cluster.client.codec;

import com.alibaba.csp.sentinel.util.SpiLoader;
import com.alibaba.csp.sentinel.spi.SpiLoader;
import com.alibaba.csp.sentinel.cluster.codec.request.RequestEntityWriter;
import com.alibaba.csp.sentinel.cluster.codec.response.ResponseEntityDecoder;
import com.alibaba.csp.sentinel.log.RecordLog;
Expand All @@ -34,15 +34,15 @@ public final class ClientEntityCodecProvider {
}

private static void resolveInstance() {
RequestEntityWriter writer = SpiLoader.loadFirstInstance(RequestEntityWriter.class);
RequestEntityWriter writer = SpiLoader.of(RequestEntityWriter.class).loadFirstInstance();
if (writer == null) {
RecordLog.warn("[ClientEntityCodecProvider] No existing request entity writer, resolve failed");
} else {
requestEntityWriter = writer;
RecordLog.info("[ClientEntityCodecProvider] Request entity writer resolved: {}",
requestEntityWriter.getClass().getCanonicalName());
}
ResponseEntityDecoder decoder = SpiLoader.loadFirstInstance(ResponseEntityDecoder.class);
ResponseEntityDecoder decoder = SpiLoader.of(ResponseEntityDecoder.class).loadFirstInstance();
if (decoder == null) {
RecordLog.warn("[ClientEntityCodecProvider] No existing response entity decoder, resolve failed");
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.alibaba.csp.sentinel.cluster.flow.rule.ClusterParamFlowRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.spi.Spi;

import java.util.Collection;

Expand All @@ -31,6 +32,7 @@
* @author Eric Zhao
* @since 1.4.0
*/
@Spi(isDefault = true)
public class DefaultTokenService implements TokenService {

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@
package com.alibaba.csp.sentinel.cluster.server;

import com.alibaba.csp.sentinel.cluster.TokenService;
import com.alibaba.csp.sentinel.cluster.flow.DefaultTokenService;
import com.alibaba.csp.sentinel.log.RecordLog;
import com.alibaba.csp.sentinel.util.SpiLoader;
import com.alibaba.csp.sentinel.spi.SpiLoader;

/**
* @author Eric Zhao
Expand All @@ -37,7 +36,7 @@ public static TokenService getService() {
}

private static void resolveTokenServiceSpi() {
service = SpiLoader.loadFirstInstanceOrDefault(TokenService.class, DefaultTokenService.class);
service = SpiLoader.of(TokenService.class).loadFirstInstanceOrDefault();
if (service != null) {
RecordLog.info("[TokenServiceProvider] Global token service resolved: "
+ service.getClass().getCanonicalName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import com.alibaba.csp.sentinel.cluster.codec.request.RequestEntityDecoder;
import com.alibaba.csp.sentinel.cluster.codec.response.ResponseEntityWriter;
import com.alibaba.csp.sentinel.log.RecordLog;
import com.alibaba.csp.sentinel.util.SpiLoader;
import com.alibaba.csp.sentinel.spi.SpiLoader;

/**
* @author Eric Zhao
Expand All @@ -34,15 +34,15 @@ public final class ServerEntityCodecProvider {
}

private static void resolveInstance() {
ResponseEntityWriter writer = SpiLoader.loadFirstInstance(ResponseEntityWriter.class);
ResponseEntityWriter writer = SpiLoader.of(ResponseEntityWriter.class).loadFirstInstance();
if (writer == null) {
RecordLog.warn("[ServerEntityCodecProvider] No existing response entity writer, resolve failed");
} else {
responseEntityWriter = writer;
RecordLog.info("[ServerEntityCodecProvider] Response entity writer resolved: {}",
responseEntityWriter.getClass().getCanonicalName());
}
RequestEntityDecoder decoder = SpiLoader.loadFirstInstance(RequestEntityDecoder.class);
RequestEntityDecoder decoder = SpiLoader.of(RequestEntityDecoder.class).loadFirstInstance();
if (decoder == null) {
RecordLog.warn("[ServerEntityCodecProvider] No existing request entity decoder, resolve failed");
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
*/
package com.alibaba.csp.sentinel.cluster.server.processor;

import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;

import com.alibaba.csp.sentinel.cluster.annotation.RequestType;
import com.alibaba.csp.sentinel.spi.ServiceLoaderUtil;
import com.alibaba.csp.sentinel.spi.SpiLoader;
import com.alibaba.csp.sentinel.util.AssertUtil;

/**
Expand All @@ -31,15 +31,13 @@ public final class RequestProcessorProvider {

private static final Map<Integer, RequestProcessor> PROCESSOR_MAP = new ConcurrentHashMap<>();

private static final ServiceLoader<RequestProcessor> SERVICE_LOADER = ServiceLoaderUtil.getServiceLoader(
RequestProcessor.class);

static {
loadAndInit();
}

private static void loadAndInit() {
for (RequestProcessor processor : SERVICE_LOADER) {
List<RequestProcessor> processors = SpiLoader.of(RequestProcessor.class).loadInstanceList();
for (RequestProcessor processor : processors) {
Integer type = parseRequestType(processor);
if (type != null) {
PROCESSOR_MAP.put(type, processor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,17 @@ public final class Constants {
*/
public static volatile boolean ON = true;

/**
* Order of default processor slots
*/
public static final int ORDER_NODE_SELECTOR_SLOT = -10000;
public static final int ORDER_CLUSTER_BUILDER_SLOT = -9000;
public static final int ORDER_LOG_SLOT = -8000;
public static final int ORDER_STATISTIC_SLOT = -7000;
public static final int ORDER_AUTHORITY_SLOT = -6000;
public static final int ORDER_SYSTEM_SLOT = -5000;
public static final int ORDER_FLOW_SLOT = -2000;
public static final int ORDER_DEGRADE_SLOT = -1000;

private Constants() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
package com.alibaba.csp.sentinel.cluster.client;

import com.alibaba.csp.sentinel.log.RecordLog;
import com.alibaba.csp.sentinel.util.SpiLoader;
import com.alibaba.csp.sentinel.spi.SpiLoader;

/**
* Provider for a universal {@link ClusterTokenClient} instance.
Expand All @@ -38,7 +38,7 @@ public static ClusterTokenClient getClient() {
}

private static void resolveTokenClientInstance() {
ClusterTokenClient resolvedClient = SpiLoader.loadFirstInstance(ClusterTokenClient.class);
ClusterTokenClient resolvedClient = SpiLoader.of(ClusterTokenClient.class).loadFirstInstance();
if (resolvedClient == null) {
RecordLog.info(
"[TokenClientProvider] No existing cluster token client, cluster client mode will not be activated");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
package com.alibaba.csp.sentinel.cluster.server;

import com.alibaba.csp.sentinel.log.RecordLog;
import com.alibaba.csp.sentinel.util.SpiLoader;
import com.alibaba.csp.sentinel.spi.SpiLoader;

/**
* @author Eric Zhao
Expand All @@ -31,7 +31,7 @@ public final class EmbeddedClusterTokenServerProvider {
}

private static void resolveInstance() {
EmbeddedClusterTokenServer s = SpiLoader.loadFirstInstance(EmbeddedClusterTokenServer.class);
EmbeddedClusterTokenServer s = SpiLoader.of(EmbeddedClusterTokenServer.class).loadFirstInstance();
if (s == null) {
RecordLog.warn("[EmbeddedClusterTokenServerProvider] No existing cluster token server, cluster server mode will not be activated");
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ public final class SentinelConfig {
*/
public static final int APP_TYPE_COMMON = 0;

/**
* Parameter value for using context classloader.
*/
private static final String CLASSLOADER_CONTEXT = "context";

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

private static int appType = APP_TYPE_COMMON;
Expand Down Expand Up @@ -286,6 +291,15 @@ private static void resolveAppName() {
private static String toEnvKey(/*@NotBlank*/ String propKey) {
return propKey.toUpperCase().replace('.', '_');
}
/**
* Whether use context classloader via config parameter
*
* @return Whether use context classloader
*/
public static boolean shouldUseContextClassloader() {
String classloaderConf = SentinelConfig.getConfig(SentinelConfig.SPI_CLASSLOADER);
return CLASSLOADER_CONTEXT.equalsIgnoreCase(classloaderConf);
}

private SentinelConfig() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import java.util.concurrent.atomic.AtomicBoolean;

import com.alibaba.csp.sentinel.log.RecordLog;
import com.alibaba.csp.sentinel.spi.ServiceLoaderUtil;
import com.alibaba.csp.sentinel.spi.SpiLoader;

/**
* Load registered init functions and execute in order.
Expand All @@ -43,9 +43,9 @@ public static void doInit() {
return;
}
try {
ServiceLoader<InitFunc> loader = ServiceLoaderUtil.getServiceLoader(InitFunc.class);
List<InitFunc> initFuncs = SpiLoader.of(InitFunc.class).loadInstanceListSorted();
List<OrderWrapper> initList = new ArrayList<OrderWrapper>();
for (InitFunc initFunc : loader) {
for (InitFunc initFunc : initFuncs) {
RecordLog.info("[InitExecutor] Found init func: {}", initFunc.getClass().getCanonicalName());
insertSorted(initList, initFunc);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import java.util.List;

import com.alibaba.csp.sentinel.log.RecordLog;
import com.alibaba.csp.sentinel.util.SpiLoader;
import com.alibaba.csp.sentinel.spi.SpiLoader;

/**
* Get all {@link MetricExtension} via SPI.
Expand All @@ -35,7 +35,7 @@ public class MetricExtensionProvider {
}

private static void resolveInstance() {
List<MetricExtension> extensions = SpiLoader.loadInstanceList(MetricExtension.class);
List<MetricExtension> extensions = SpiLoader.of(MetricExtension.class).loadInstanceList();

if (extensions.isEmpty()) {
RecordLog.info("[MetricExtensionProvider] No existing MetricExtension found");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

import com.alibaba.csp.sentinel.log.RecordLog;
import com.alibaba.csp.sentinel.slots.DefaultSlotChainBuilder;
import com.alibaba.csp.sentinel.util.SpiLoader;
import com.alibaba.csp.sentinel.spi.SpiLoader;

/**
* A provider for creating slot chains via resolved slot chain builder SPI.
Expand All @@ -41,7 +41,7 @@ public static ProcessorSlotChain newSlotChain() {
}

// Resolve the slot chain builder SPI.
slotChainBuilder = SpiLoader.loadFirstInstanceOrDefault(SlotChainBuilder.class, DefaultSlotChainBuilder.class);
slotChainBuilder = SpiLoader.of(SlotChainBuilder.class).loadFirstInstanceOrDefault();

if (slotChainBuilder == null) {
// Should not go through here.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
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.util.SpiLoader;
import com.alibaba.csp.sentinel.spi.Spi;
import com.alibaba.csp.sentinel.spi.SpiLoader;

import java.util.List;

Expand All @@ -31,14 +32,14 @@
* @author qinan.qn
* @author leyou
*/
@Spi(isDefault = true)
public class DefaultSlotChainBuilder implements SlotChainBuilder {

@Override
public ProcessorSlotChain build() {
ProcessorSlotChain chain = new DefaultProcessorSlotChain();

// Note: the instances of ProcessorSlot should be different, since they are not stateless.
List<ProcessorSlot> sortedSlotList = SpiLoader.loadPrototypeInstanceListSorted(ProcessorSlot.class);
List<ProcessorSlot> sortedSlotList = SpiLoader.of(ProcessorSlot.class).loadInstanceListSorted();
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");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,21 @@
import java.util.Map;
import java.util.Set;

import com.alibaba.csp.sentinel.Constants;
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.ProcessorSlot;
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
import com.alibaba.csp.sentinel.spi.SpiOrder;
import com.alibaba.csp.sentinel.spi.Spi;

/**
* A {@link ProcessorSlot} that dedicates to {@link AuthorityRule} checking.
*
* @author leyou
* @author Eric Zhao
*/
@SpiOrder(-6000)
@Spi(order = Constants.ORDER_AUTHORITY_SLOT)
public class AuthoritySlot extends AbstractLinkedProcessorSlot<DefaultNode> {

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import java.util.List;

import com.alibaba.csp.sentinel.Constants;
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.context.Context;
import com.alibaba.csp.sentinel.node.DefaultNode;
Expand All @@ -25,15 +26,15 @@
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreaker;
import com.alibaba.csp.sentinel.spi.SpiOrder;
import com.alibaba.csp.sentinel.spi.Spi;

/**
* A {@link ProcessorSlot} dedicates to circuit breaking.
*
* @author Carpenter Lee
* @author Eric Zhao
*/
@SpiOrder(-1000)
@Spi(order = Constants.ORDER_DEGRADE_SLOT)
public class DegradeSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

@Override
Expand Down
Loading