Skip to content

Commit ca2f4d9

Browse files
authored
Support extensible slot chain builder using SPI mechanism (#145)
- Support extensible `SlotChainBuilder` using SPI mechanism - Add a `SlotChainProvider` to load slot chain builder and create new slot chains Signed-off-by: Eric Zhao <[email protected]>
1 parent d142a07 commit ca2f4d9

File tree

6 files changed

+91
-11
lines changed

6 files changed

+91
-11
lines changed

sentinel-core/src/main/java/com/alibaba/csp/sentinel/CtSph.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.alibaba.csp.sentinel.slotchain.ProcessorSlot;
2929
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotChain;
3030
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
31+
import com.alibaba.csp.sentinel.slotchain.SlotChainProvider;
3132
import com.alibaba.csp.sentinel.slotchain.StringResourceWrapper;
3233
import com.alibaba.csp.sentinel.slots.block.BlockException;
3334
import com.alibaba.csp.sentinel.slots.block.Rule;
@@ -133,7 +134,7 @@ private ProcessorSlot<Object> lookProcessChain(ResourceWrapper resourceWrapper)
133134
return null;
134135
}
135136

136-
chain = Env.slotsChainbuilder.build();
137+
chain = SlotChainProvider.newSlotChain();
137138
Map<ResourceWrapper, ProcessorSlotChain> newMap = new HashMap<ResourceWrapper, ProcessorSlotChain>(
138139
chainMap.size() + 1);
139140
newMap.putAll(chainMap);

sentinel-core/src/main/java/com/alibaba/csp/sentinel/Env.java

-3
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,12 @@
1818
import com.alibaba.csp.sentinel.init.InitExecutor;
1919
import com.alibaba.csp.sentinel.node.DefaultNodeBuilder;
2020
import com.alibaba.csp.sentinel.node.NodeBuilder;
21-
import com.alibaba.csp.sentinel.slots.DefaultSlotsChainBuilder;
22-
import com.alibaba.csp.sentinel.slots.SlotsChainBuilder;
2321

2422
/**
2523
* @author jialiang.linjl
2624
*/
2725
public class Env {
2826

29-
public static final SlotsChainBuilder slotsChainbuilder = new DefaultSlotsChainBuilder();
3027
public static final NodeBuilder nodeBuilder = new DefaultNodeBuilder();
3128
public static final Sph sph = new CtSph();
3229

sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/SlotsChainBuilder.java renamed to sentinel-core/src/main/java/com/alibaba/csp/sentinel/slotchain/SlotChainBuilder.java

+7-6
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,21 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package com.alibaba.csp.sentinel.slots;
17-
18-
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotChain;
16+
package com.alibaba.csp.sentinel.slotchain;
1917

2018
/**
19+
* The builder for processor slot chain.
20+
*
2121
* @author qinan.qn
2222
* @author leyou
23+
* @author Eric Zhao
2324
*/
24-
public interface SlotsChainBuilder {
25+
public interface SlotChainBuilder {
2526

2627
/**
27-
* Helper method to create processor slot chain.
28+
* Build the processor slot chain.
2829
*
29-
* @return a processor slot that chain some slots together.
30+
* @return a processor slot that chain some slots together
3031
*/
3132
ProcessorSlotChain build();
3233
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright 1999-2018 Alibaba Group Holding Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.alibaba.csp.sentinel.slotchain;
17+
18+
import java.util.ArrayList;
19+
import java.util.List;
20+
import java.util.ServiceLoader;
21+
22+
import com.alibaba.csp.sentinel.log.RecordLog;
23+
import com.alibaba.csp.sentinel.slots.DefaultSlotChainBuilder;
24+
25+
/**
26+
* A provider for creating slot chains via resolved slot chain builder SPI.
27+
*
28+
* @author Eric Zhao
29+
* @since 0.2.0
30+
*/
31+
public final class SlotChainProvider {
32+
33+
private static volatile SlotChainBuilder builder = null;
34+
35+
private static final ServiceLoader<SlotChainBuilder> LOADER = ServiceLoader.load(SlotChainBuilder.class);
36+
37+
/**
38+
* The load and pick process is not thread-safe, but it's okay since the method should be only invoked
39+
* via {@code lookProcessChain} in {@link com.alibaba.csp.sentinel.CtSph} under lock.
40+
*
41+
* @return new created slot chain
42+
*/
43+
public static ProcessorSlotChain newSlotChain() {
44+
if (builder != null) {
45+
return builder.build();
46+
}
47+
48+
resolveSlotChainBuilder();
49+
50+
if (builder == null) {
51+
RecordLog.warn("[SlotChainProvider] Wrong state when resolving slot chain builder, using default");
52+
builder = new DefaultSlotChainBuilder();
53+
}
54+
return builder.build();
55+
}
56+
57+
private static void resolveSlotChainBuilder() {
58+
List<SlotChainBuilder> list = new ArrayList<SlotChainBuilder>();
59+
boolean hasOther = false;
60+
for (SlotChainBuilder builder : LOADER) {
61+
if (builder.getClass() != DefaultSlotChainBuilder.class) {
62+
hasOther = true;
63+
list.add(builder);
64+
}
65+
}
66+
if (hasOther) {
67+
builder = list.get(0);
68+
} else {
69+
// No custom builder, using default.
70+
builder = new DefaultSlotChainBuilder();
71+
}
72+
73+
RecordLog.info("[SlotChainProvider] Global slot chain builder resolved: "
74+
+ builder.getClass().getCanonicalName());
75+
}
76+
77+
private SlotChainProvider() {}
78+
}

sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/DefaultSlotsChainBuilder.java renamed to sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/DefaultSlotChainBuilder.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import com.alibaba.csp.sentinel.slotchain.DefaultProcessorSlotChain;
1919
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotChain;
20+
import com.alibaba.csp.sentinel.slotchain.SlotChainBuilder;
2021
import com.alibaba.csp.sentinel.slots.block.authority.AuthoritySlot;
2122
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeSlot;
2223
import com.alibaba.csp.sentinel.slots.block.flow.FlowSlot;
@@ -32,7 +33,7 @@
3233
* @author qinan.qn
3334
* @author leyou
3435
*/
35-
public class DefaultSlotsChainBuilder implements SlotsChainBuilder {
36+
public class DefaultSlotChainBuilder implements SlotChainBuilder {
3637

3738
@Override
3839
public ProcessorSlotChain build() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Default slot chain builder
2+
com.alibaba.csp.sentinel.slots.DefaultSlotChainBuilder

0 commit comments

Comments
 (0)