diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/CtSph.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/CtSph.java index 43f3379a..8c0385bb 100755 --- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/CtSph.java +++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/CtSph.java @@ -28,6 +28,7 @@ import com.alibaba.csp.sentinel.slotchain.MethodResourceWrapper; import com.alibaba.csp.sentinel.slotchain.ProcessorSlot; import com.alibaba.csp.sentinel.slotchain.ProcessorSlotChain; import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; +import com.alibaba.csp.sentinel.slotchain.SlotChainProvider; import com.alibaba.csp.sentinel.slotchain.StringResourceWrapper; import com.alibaba.csp.sentinel.slots.block.BlockException; import com.alibaba.csp.sentinel.slots.block.Rule; @@ -133,7 +134,7 @@ public class CtSph implements Sph { return null; } - chain = Env.slotsChainbuilder.build(); + chain = SlotChainProvider.newSlotChain(); Map newMap = new HashMap( chainMap.size() + 1); newMap.putAll(chainMap); diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/Env.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/Env.java index 4a145a24..31a69291 100755 --- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/Env.java +++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/Env.java @@ -18,15 +18,12 @@ package com.alibaba.csp.sentinel; import com.alibaba.csp.sentinel.init.InitExecutor; import com.alibaba.csp.sentinel.node.DefaultNodeBuilder; import com.alibaba.csp.sentinel.node.NodeBuilder; -import com.alibaba.csp.sentinel.slots.DefaultSlotsChainBuilder; -import com.alibaba.csp.sentinel.slots.SlotsChainBuilder; /** * @author jialiang.linjl */ public class Env { - public static final SlotsChainBuilder slotsChainbuilder = new DefaultSlotsChainBuilder(); public static final NodeBuilder nodeBuilder = new DefaultNodeBuilder(); public static final Sph sph = new CtSph(); diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/SlotsChainBuilder.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slotchain/SlotChainBuilder.java similarity index 73% rename from sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/SlotsChainBuilder.java rename to sentinel-core/src/main/java/com/alibaba/csp/sentinel/slotchain/SlotChainBuilder.java index 59db01a6..e0b2e7ac 100755 --- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/SlotsChainBuilder.java +++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slotchain/SlotChainBuilder.java @@ -13,20 +13,21 @@ * 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.ProcessorSlotChain; +package com.alibaba.csp.sentinel.slotchain; /** + * The builder for processor slot chain. + * * @author qinan.qn * @author leyou + * @author Eric Zhao */ -public interface SlotsChainBuilder { +public interface SlotChainBuilder { /** - * Helper method to create processor slot chain. + * Build the processor slot chain. * - * @return a processor slot that chain some slots together. + * @return a processor slot that chain some slots together */ ProcessorSlotChain build(); } diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slotchain/SlotChainProvider.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slotchain/SlotChainProvider.java new file mode 100644 index 00000000..dedad3c1 --- /dev/null +++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slotchain/SlotChainProvider.java @@ -0,0 +1,78 @@ +/* + * 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.slotchain; + +import java.util.ArrayList; +import java.util.List; +import java.util.ServiceLoader; + +import com.alibaba.csp.sentinel.log.RecordLog; +import com.alibaba.csp.sentinel.slots.DefaultSlotChainBuilder; + +/** + * A provider for creating slot chains via resolved slot chain builder SPI. + * + * @author Eric Zhao + * @since 0.2.0 + */ +public final class SlotChainProvider { + + private static volatile SlotChainBuilder builder = null; + + private static final ServiceLoader LOADER = ServiceLoader.load(SlotChainBuilder.class); + + /** + * The load and pick process is not thread-safe, but it's okay since the method should be only invoked + * via {@code lookProcessChain} in {@link com.alibaba.csp.sentinel.CtSph} under lock. + * + * @return new created slot chain + */ + public static ProcessorSlotChain newSlotChain() { + if (builder != null) { + return builder.build(); + } + + resolveSlotChainBuilder(); + + if (builder == null) { + RecordLog.warn("[SlotChainProvider] Wrong state when resolving slot chain builder, using default"); + builder = new DefaultSlotChainBuilder(); + } + return builder.build(); + } + + private static void resolveSlotChainBuilder() { + List list = new ArrayList(); + boolean hasOther = false; + for (SlotChainBuilder builder : LOADER) { + if (builder.getClass() != DefaultSlotChainBuilder.class) { + hasOther = true; + list.add(builder); + } + } + if (hasOther) { + builder = list.get(0); + } else { + // No custom builder, using default. + builder = new DefaultSlotChainBuilder(); + } + + RecordLog.info("[SlotChainProvider] Global slot chain builder resolved: " + + builder.getClass().getCanonicalName()); + } + + private SlotChainProvider() {} +} diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/DefaultSlotsChainBuilder.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/DefaultSlotChainBuilder.java similarity index 93% rename from sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/DefaultSlotsChainBuilder.java rename to sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/DefaultSlotChainBuilder.java index 5da3d5fa..ccb91226 100755 --- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/DefaultSlotsChainBuilder.java +++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/DefaultSlotChainBuilder.java @@ -17,6 +17,7 @@ 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; @@ -32,7 +33,7 @@ import com.alibaba.csp.sentinel.slots.system.SystemSlot; * @author qinan.qn * @author leyou */ -public class DefaultSlotsChainBuilder implements SlotsChainBuilder { +public class DefaultSlotChainBuilder implements SlotChainBuilder { @Override public ProcessorSlotChain build() { diff --git a/sentinel-core/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.SlotChainBuilder b/sentinel-core/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.SlotChainBuilder new file mode 100644 index 00000000..1c2d62d0 --- /dev/null +++ b/sentinel-core/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.slotchain.SlotChainBuilder @@ -0,0 +1,2 @@ +# Default slot chain builder +com.alibaba.csp.sentinel.slots.DefaultSlotChainBuilder \ No newline at end of file