15
15
*/
16
16
package com .alibaba .csp .sentinel .slots .block .degrade ;
17
17
18
- import com .alibaba .csp .sentinel .concurrent .NamedThreadFactory ;
19
18
import com .alibaba .csp .sentinel .context .Context ;
20
- import com .alibaba .csp .sentinel .node .ClusterNode ;
21
19
import com .alibaba .csp .sentinel .node .DefaultNode ;
22
20
import com .alibaba .csp .sentinel .slots .block .AbstractRule ;
23
21
import com .alibaba .csp .sentinel .slots .block .RuleConstant ;
24
- import com .alibaba .csp .sentinel .slots .clusterbuilder .ClusterBuilderSlot ;
25
22
26
- import java .util .concurrent .Executors ;
27
- import java .util .concurrent .ScheduledExecutorService ;
28
- import java .util .concurrent .TimeUnit ;
29
- import java .util .concurrent .atomic .AtomicBoolean ;
30
- import java .util .concurrent .atomic .AtomicLong ;
23
+ import java .util .Objects ;
31
24
32
25
/**
33
26
* <p>
52
45
* </ul>
53
46
*
54
47
* @author jialiang.linjl
48
+ * @author Eric Zhao
55
49
*/
56
50
public class DegradeRule extends AbstractRule {
57
51
58
- @ SuppressWarnings ("PMD.ThreadPoolCreationRule" )
59
- private static ScheduledExecutorService pool = Executors .newScheduledThreadPool (
60
- Runtime .getRuntime ().availableProcessors (), new NamedThreadFactory ("sentinel-degrade-reset-task" , true ));
61
-
62
52
public DegradeRule () {}
63
53
64
54
public DegradeRule (String resourceName ) {
65
55
setResource (resourceName );
66
56
}
67
57
68
58
/**
69
- * RT threshold or exception ratio threshold count.
59
+ * Circuit breaking strategy (0: average RT, 1: exception ratio, 2: exception count) .
70
60
*/
71
- private double count ;
61
+ private int grade = RuleConstant . DEGRADE_GRADE_RT ;
72
62
73
63
/**
74
- * Degrade recover timeout (in seconds) when degradation occurs .
64
+ * Threshold count .
75
65
*/
76
- private int timeWindow ;
66
+ private double count ;
77
67
78
68
/**
79
- * Degrade strategy (0: average RT, 1: exception ratio, 2: exception count).
69
+ * Recovery timeout (in seconds) when circuit breaker opens. After the timeout, the circuit breaker will
70
+ * transform to half-open state for trying a few requests.
80
71
*/
81
- private int grade = RuleConstant . DEGRADE_GRADE_RT ;
72
+ private int timeWindow ;
82
73
83
74
/**
84
- * Minimum number of consecutive slow requests that can trigger RT circuit breaking.
75
+ * Minimum number of requests (in an active statistic time span) that can trigger circuit breaking.
85
76
*
86
77
* @since 1.7.0
87
78
*/
88
- private int rtSlowRequestAmount = RuleConstant .DEGRADE_DEFAULT_SLOW_REQUEST_AMOUNT ;
79
+ private int minRequestAmount = RuleConstant .DEGRADE_DEFAULT_MIN_REQUEST_AMOUNT ;
89
80
90
81
/**
91
- * Minimum number of requests (in an active statistic time span) that can trigger circuit breaking.
92
- *
93
- * @since 1.7.0
82
+ * The threshold of slow request ratio in RT mode.
94
83
*/
95
- private int minRequestAmount = RuleConstant .DEGRADE_DEFAULT_MIN_REQUEST_AMOUNT ;
84
+ private double slowRatioThreshold = 1.0d ;
85
+
86
+ private int statIntervalMs = 1000 ;
96
87
97
88
public int getGrade () {
98
89
return grade ;
@@ -121,21 +112,30 @@ public DegradeRule setTimeWindow(int timeWindow) {
121
112
return this ;
122
113
}
123
114
124
- public int getRtSlowRequestAmount () {
125
- return rtSlowRequestAmount ;
115
+ public int getMinRequestAmount () {
116
+ return minRequestAmount ;
126
117
}
127
118
128
- public DegradeRule setRtSlowRequestAmount (int rtSlowRequestAmount ) {
129
- this .rtSlowRequestAmount = rtSlowRequestAmount ;
119
+ public DegradeRule setMinRequestAmount (int minRequestAmount ) {
120
+ this .minRequestAmount = minRequestAmount ;
130
121
return this ;
131
122
}
132
123
133
- public int getMinRequestAmount () {
134
- return minRequestAmount ;
124
+ public double getSlowRatioThreshold () {
125
+ return slowRatioThreshold ;
135
126
}
136
127
137
- public DegradeRule setMinRequestAmount (int minRequestAmount ) {
138
- this .minRequestAmount = minRequestAmount ;
128
+ public DegradeRule setSlowRatioThreshold (double slowRatioThreshold ) {
129
+ this .slowRatioThreshold = slowRatioThreshold ;
130
+ return this ;
131
+ }
132
+
133
+ public int getStatIntervalMs () {
134
+ return statIntervalMs ;
135
+ }
136
+
137
+ public DegradeRule setStatIntervalMs (int statIntervalMs ) {
138
+ this .statIntervalMs = statIntervalMs ;
139
139
return this ;
140
140
}
141
141
@@ -144,23 +144,19 @@ public boolean equals(Object o) {
144
144
if (this == o ) { return true ; }
145
145
if (o == null || getClass () != o .getClass ()) { return false ; }
146
146
if (!super .equals (o )) { return false ; }
147
- DegradeRule that = (DegradeRule ) o ;
148
- return Double .compare (that .count , count ) == 0 &&
149
- timeWindow == that .timeWindow &&
150
- grade == that .grade &&
151
- rtSlowRequestAmount == that .rtSlowRequestAmount &&
152
- minRequestAmount == that .minRequestAmount ;
147
+ DegradeRule rule = (DegradeRule )o ;
148
+ return Double .compare (rule .count , count ) == 0 &&
149
+ timeWindow == rule .timeWindow &&
150
+ grade == rule .grade &&
151
+ minRequestAmount == rule .minRequestAmount &&
152
+ Double .compare (rule .slowRatioThreshold , slowRatioThreshold ) == 0 &&
153
+ statIntervalMs == rule .statIntervalMs ;
153
154
}
154
155
155
156
@ Override
156
157
public int hashCode () {
157
- int result = super .hashCode ();
158
- result = 31 * result + new Double (count ).hashCode ();
159
- result = 31 * result + timeWindow ;
160
- result = 31 * result + grade ;
161
- result = 31 * result + rtSlowRequestAmount ;
162
- result = 31 * result + minRequestAmount ;
163
- return result ;
158
+ return Objects .hash (super .hashCode (), count , timeWindow , grade , minRequestAmount ,
159
+ slowRatioThreshold , statIntervalMs );
164
160
}
165
161
166
162
@ Override
@@ -171,84 +167,15 @@ public String toString() {
171
167
", count=" + count +
172
168
", limitApp=" + getLimitApp () +
173
169
", timeWindow=" + timeWindow +
174
- ", rtSlowRequestAmount=" + rtSlowRequestAmount +
175
170
", minRequestAmount=" + minRequestAmount +
176
- "}" ;
171
+ ", slowRatioThreshold=" + slowRatioThreshold +
172
+ ", statIntervalMs=" + statIntervalMs +
173
+ '}' ;
177
174
}
178
175
179
- // Internal implementation (will be deprecated and moved outside).
180
-
181
- private AtomicLong passCount = new AtomicLong (0 );
182
- private final AtomicBoolean cut = new AtomicBoolean (false );
183
-
184
176
@ Override
185
- public boolean passCheck (Context context , DefaultNode node , int acquireCount , Object ... args ) {
186
- if (cut .get ()) {
187
- return false ;
188
- }
189
-
190
- ClusterNode clusterNode = ClusterBuilderSlot .getClusterNode (this .getResource ());
191
- if (clusterNode == null ) {
192
- return true ;
193
- }
194
-
195
- if (grade == RuleConstant .DEGRADE_GRADE_RT ) {
196
- double rt = clusterNode .avgRt ();
197
- if (rt < this .count ) {
198
- passCount .set (0 );
199
- return true ;
200
- }
201
-
202
- // Sentinel will degrade the service only if count exceeds.
203
- if (passCount .incrementAndGet () < rtSlowRequestAmount ) {
204
- return true ;
205
- }
206
- } else if (grade == RuleConstant .DEGRADE_GRADE_EXCEPTION_RATIO ) {
207
- double exception = clusterNode .exceptionQps ();
208
- double success = clusterNode .successQps ();
209
- double total = clusterNode .totalQps ();
210
- // If total amount is less than minRequestAmount, the request will pass.
211
- if (total < minRequestAmount ) {
212
- return true ;
213
- }
214
-
215
- // In the same aligned statistic time window,
216
- // "success" (aka. completed count) = exception count + non-exception count (realSuccess)
217
- double realSuccess = success - exception ;
218
- if (realSuccess <= 0 && exception < minRequestAmount ) {
219
- return true ;
220
- }
221
-
222
- if (exception / success < count ) {
223
- return true ;
224
- }
225
- } else if (grade == RuleConstant .DEGRADE_GRADE_EXCEPTION_COUNT ) {
226
- double exception = clusterNode .totalException ();
227
- if (exception < count ) {
228
- return true ;
229
- }
230
- }
231
-
232
- if (cut .compareAndSet (false , true )) {
233
- ResetTask resetTask = new ResetTask (this );
234
- pool .schedule (resetTask , timeWindow , TimeUnit .SECONDS );
235
- }
236
-
177
+ @ Deprecated
178
+ public boolean passCheck (Context context , DefaultNode node , int count , Object ... args ) {
237
179
return false ;
238
180
}
239
-
240
- private static final class ResetTask implements Runnable {
241
-
242
- private DegradeRule rule ;
243
-
244
- ResetTask (DegradeRule rule ) {
245
- this .rule = rule ;
246
- }
247
-
248
- @ Override
249
- public void run () {
250
- rule .passCount .set (0 );
251
- rule .cut .set (false );
252
- }
253
- }
254
181
}
0 commit comments