1
2
3
4
5
6
7
8
9
10
11
12 package org.apache.hadoop.hbase.quotas;
13
14 import static org.junit.Assert.assertEquals;
15 import static org.junit.Assert.assertFalse;
16 import static org.junit.Assert.assertTrue;
17
18 import java.util.concurrent.TimeUnit;
19
20 import org.apache.hadoop.hbase.testclassification.SmallTests;
21 import org.apache.hadoop.hbase.util.ManualEnvironmentEdge;
22 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
23 import org.junit.Test;
24 import org.junit.experimental.categories.Category;
25
26
27
28
29 @Category({ SmallTests.class })
30 public class TestRateLimiter {
31 @Test
32 public void testWaitIntervalTimeUnitSeconds() {
33 testWaitInterval(TimeUnit.SECONDS, 10, 100);
34 }
35
36 @Test
37 public void testWaitIntervalTimeUnitMinutes() {
38 testWaitInterval(TimeUnit.MINUTES, 10, 6000);
39 }
40
41 @Test
42 public void testWaitIntervalTimeUnitHours() {
43 testWaitInterval(TimeUnit.HOURS, 10, 360000);
44 }
45
46 @Test
47 public void testWaitIntervalTimeUnitDays() {
48 testWaitInterval(TimeUnit.DAYS, 10, 8640000);
49 }
50
51 private void testWaitInterval(final TimeUnit timeUnit, final long limit,
52 final long expectedWaitInterval) {
53 RateLimiter limiter = new AverageIntervalRateLimiter();
54 limiter.set(limit, timeUnit);
55
56 long nowTs = 0;
57
58
59 for (int i = 0; i < (limit - 1); ++i) {
60 assertTrue(limiter.canExecute());
61 limiter.consume();
62 long waitInterval = limiter.waitInterval();
63 assertEquals(0, waitInterval);
64 }
65
66 for (int i = 0; i < (limit * 4); ++i) {
67
68
69 limiter.setNextRefillTime(limiter.getNextRefillTime() - nowTs);
70 assertTrue(limiter.canExecute());
71 assertEquals(0, limiter.waitInterval());
72 limiter.consume();
73
74 long waitInterval = limiter.waitInterval();
75 assertEquals(expectedWaitInterval, waitInterval);
76
77
78 nowTs = waitInterval;
79
80
81 long temp = nowTs + 500;
82 limiter.setNextRefillTime(limiter.getNextRefillTime() + temp);
83 assertFalse(limiter.canExecute());
84
85 limiter.setNextRefillTime(limiter.getNextRefillTime() - temp);
86 }
87 }
88
89 @Test
90 public void testOverconsumptionAverageIntervalRefillStrategy() {
91 RateLimiter limiter = new AverageIntervalRateLimiter();
92 limiter.set(10, TimeUnit.SECONDS);
93
94
95
96 assertTrue(limiter.canExecute());
97 limiter.consume(20);
98
99 assertEquals(100, limiter.waitInterval(1));
100
101 assertEquals(1000, limiter.waitInterval(10));
102
103 limiter.setNextRefillTime(limiter.getNextRefillTime() - 900);
104
105 assertTrue(limiter.canExecute(1));
106 limiter.setNextRefillTime(limiter.getNextRefillTime() - 100);
107
108 assertTrue(limiter.canExecute());
109 assertEquals(0, limiter.waitInterval());
110 }
111
112 @Test
113 public void testOverconsumptionFixedIntervalRefillStrategy() throws InterruptedException {
114 RateLimiter limiter = new FixedIntervalRateLimiter();
115 limiter.set(10, TimeUnit.SECONDS);
116
117
118
119 assertTrue(limiter.canExecute());
120 limiter.consume(20);
121
122 assertEquals(1000, limiter.waitInterval(1));
123
124 assertEquals(1000, limiter.waitInterval(10));
125
126 limiter.setNextRefillTime(limiter.getNextRefillTime() - 900);
127
128 assertFalse(limiter.canExecute(1));
129 limiter.setNextRefillTime(limiter.getNextRefillTime() - 100);
130
131
132 assertTrue(limiter.canExecute());
133 assertEquals(0, limiter.waitInterval());
134 }
135
136 @Test
137 public void testFixedIntervalResourceAvailability() throws Exception {
138 RateLimiter limiter = new FixedIntervalRateLimiter();
139 limiter.set(10, TimeUnit.SECONDS);
140
141 assertTrue(limiter.canExecute(10));
142 limiter.consume(3);
143 assertEquals(7, limiter.getAvailable());
144 assertFalse(limiter.canExecute(10));
145 limiter.setNextRefillTime(limiter.getNextRefillTime() - 1000);
146 assertTrue(limiter.canExecute(10));
147 assertEquals(10, limiter.getAvailable());
148 }
149
150 @Test
151 public void testLimiterBySmallerRate() throws InterruptedException {
152
153 RateLimiter limiter = new FixedIntervalRateLimiter();
154 limiter.set(10, TimeUnit.SECONDS);
155
156 int count = 0;
157 while ((count++) < 10) {
158
159 limiter.setNextRefillTime(limiter.getNextRefillTime() - 500);
160 for (int i = 0; i < 3; i++) {
161
162 assertEquals(true, limiter.canExecute());
163 limiter.consume();
164 }
165 }
166 }
167
168 @Test
169 public void testCanExecuteOfAverageIntervalRateLimiter() throws InterruptedException {
170 RateLimiter limiter = new AverageIntervalRateLimiter();
171
172 limiter.set(100, TimeUnit.SECONDS);
173 limiter.setNextRefillTime(EnvironmentEdgeManager.currentTime());
174 assertEquals(50, testCanExecuteByRate(limiter, 50));
175
176
177 limiter.set(100, TimeUnit.SECONDS);
178 limiter.setNextRefillTime(EnvironmentEdgeManager.currentTime());
179 assertEquals(100, testCanExecuteByRate(limiter, 100));
180
181
182 limiter.set(100, TimeUnit.SECONDS);
183 limiter.setNextRefillTime(EnvironmentEdgeManager.currentTime());
184 assertEquals(200, testCanExecuteByRate(limiter, 200));
185
186
187 limiter.set(100, TimeUnit.SECONDS);
188 limiter.setNextRefillTime(EnvironmentEdgeManager.currentTime());
189 assertEquals(200, testCanExecuteByRate(limiter, 500));
190 }
191
192 @Test
193 public void testCanExecuteOfFixedIntervalRateLimiter() throws InterruptedException {
194 RateLimiter limiter = new FixedIntervalRateLimiter();
195
196 limiter.set(100, TimeUnit.SECONDS);
197 limiter.setNextRefillTime(EnvironmentEdgeManager.currentTime());
198 assertEquals(50, testCanExecuteByRate(limiter, 50));
199
200
201 limiter.set(100, TimeUnit.SECONDS);
202 limiter.setNextRefillTime(EnvironmentEdgeManager.currentTime());
203 assertEquals(100, testCanExecuteByRate(limiter, 100));
204
205
206 limiter.set(100, TimeUnit.SECONDS);
207 limiter.setNextRefillTime(EnvironmentEdgeManager.currentTime());
208 assertEquals(100, testCanExecuteByRate(limiter, 200));
209 }
210
211 public int testCanExecuteByRate(RateLimiter limiter, int rate) {
212 int request = 0;
213 int count = 0;
214 while ((request++) < rate) {
215 limiter.setNextRefillTime(limiter.getNextRefillTime() - limiter.getTimeUnitInMillis() / rate);
216 if (limiter.canExecute()) {
217 count++;
218 limiter.consume();
219 }
220 }
221 return count;
222 }
223
224 @Test
225 public void testRefillOfAverageIntervalRateLimiter() throws InterruptedException {
226 RateLimiter limiter = new AverageIntervalRateLimiter();
227 limiter.set(60, TimeUnit.SECONDS);
228 assertEquals(60, limiter.getAvailable());
229
230 assertEquals(60, limiter.refill(limiter.getLimit()));
231
232 limiter.consume(30);
233
234
235 limiter.setNextRefillTime(limiter.getNextRefillTime() - 200);
236 assertEquals(12, limiter.refill(limiter.getLimit()));
237
238
239 limiter.setNextRefillTime(limiter.getNextRefillTime() - 500);
240 assertEquals(30, limiter.refill(limiter.getLimit()));
241
242
243 limiter.setNextRefillTime(limiter.getNextRefillTime() - 1000);
244 assertEquals(60, limiter.refill(limiter.getLimit()));
245
246
247 limiter.setNextRefillTime(limiter.getNextRefillTime() - 3000);
248 assertEquals(60, limiter.refill(limiter.getLimit()));
249 limiter.setNextRefillTime(limiter.getNextRefillTime() - 5000);
250 assertEquals(60, limiter.refill(limiter.getLimit()));
251 }
252
253 @Test
254 public void testRefillOfFixedIntervalRateLimiter() throws InterruptedException {
255 RateLimiter limiter = new FixedIntervalRateLimiter();
256 limiter.set(60, TimeUnit.SECONDS);
257 assertEquals(60, limiter.getAvailable());
258
259 assertEquals(60, limiter.refill(limiter.getLimit()));
260
261 limiter.consume(30);
262
263
264 limiter.setNextRefillTime(limiter.getNextRefillTime() - 200);
265 assertEquals(0, limiter.refill(limiter.getLimit()));
266
267
268 limiter.setNextRefillTime(limiter.getNextRefillTime() - 500);
269 assertEquals(0, limiter.refill(limiter.getLimit()));
270
271
272 limiter.setNextRefillTime(limiter.getNextRefillTime() - 1000);
273 assertEquals(60, limiter.refill(limiter.getLimit()));
274
275
276 limiter.setNextRefillTime(limiter.getNextRefillTime() - 3000);
277 assertEquals(60, limiter.refill(limiter.getLimit()));
278 limiter.setNextRefillTime(limiter.getNextRefillTime() - 5000);
279 assertEquals(60, limiter.refill(limiter.getLimit()));
280 }
281
282 @Test
283 public void testUnconfiguredLimiters() throws InterruptedException {
284
285 ManualEnvironmentEdge testEdge = new ManualEnvironmentEdge();
286 EnvironmentEdgeManager.injectEdge(testEdge);
287 long limit = Long.MAX_VALUE;
288
289
290 RateLimiter avgLimiter = new AverageIntervalRateLimiter();
291 RateLimiter fixLimiter = new FixedIntervalRateLimiter();
292
293 assertEquals(limit, avgLimiter.getAvailable());
294 assertEquals(limit, fixLimiter.getAvailable());
295
296 assertTrue(avgLimiter.canExecute(limit));
297 avgLimiter.consume(limit);
298
299 assertTrue(fixLimiter.canExecute(limit));
300 fixLimiter.consume(limit);
301
302
303 assertTrue(limit == avgLimiter.getAvailable());
304 assertTrue(limit == fixLimiter.getAvailable());
305
306
307 testEdge.incValue(100);
308
309 assertTrue(avgLimiter.canExecute(limit));
310 avgLimiter.consume(limit);
311
312 assertTrue(fixLimiter.canExecute(limit));
313 fixLimiter.consume(limit);
314
315
316 assertTrue(limit == avgLimiter.getAvailable());
317 assertTrue(limit == fixLimiter.getAvailable());
318
319 EnvironmentEdgeManager.reset();
320 }
321
322 @Test
323 public void testExtremeLimiters() throws InterruptedException {
324
325 ManualEnvironmentEdge testEdge = new ManualEnvironmentEdge();
326 EnvironmentEdgeManager.injectEdge(testEdge);
327 long limit = Long.MAX_VALUE - 1;
328
329 RateLimiter avgLimiter = new AverageIntervalRateLimiter();
330 avgLimiter.set(limit, TimeUnit.SECONDS);
331 RateLimiter fixLimiter = new FixedIntervalRateLimiter();
332 fixLimiter.set(limit, TimeUnit.SECONDS);
333
334 assertEquals(limit, avgLimiter.getAvailable());
335 assertEquals(limit, fixLimiter.getAvailable());
336
337 assertTrue(avgLimiter.canExecute(limit / 2));
338 avgLimiter.consume(limit / 2);
339
340 assertTrue(fixLimiter.canExecute(limit / 2));
341 fixLimiter.consume(limit / 2);
342
343
344 assertTrue((limit - (limit / 2)) == avgLimiter.getAvailable());
345 assertTrue((limit - (limit / 2)) == fixLimiter.getAvailable());
346
347
348 testEdge.incValue(100);
349
350 assertFalse(avgLimiter.canExecute(limit));
351 assertFalse(fixLimiter.canExecute(limit));
352
353
354 testEdge.incValue(500);
355 assertTrue(avgLimiter.canExecute(limit));
356 assertFalse(fixLimiter.canExecute(limit));
357
358
359 assertTrue(limit == avgLimiter.getAvailable());
360 assertTrue((limit - (limit / 2)) == fixLimiter.getAvailable());
361
362
363 testEdge.incValue(500);
364 assertTrue(avgLimiter.canExecute(limit));
365 assertTrue(fixLimiter.canExecute(limit));
366
367
368 assertTrue(limit == avgLimiter.getAvailable());
369 assertTrue(limit == fixLimiter.getAvailable());
370
371 EnvironmentEdgeManager.reset();
372 }
373
374
375
376
377
378
379
380
381
382 @Test
383 public void testLimiterCompensationOverflow() throws InterruptedException {
384
385 long limit = Long.MAX_VALUE - 1;
386 long guessNumber = 100;
387
388
389 RateLimiter avgLimiter = new AverageIntervalRateLimiter();
390 avgLimiter.set(limit, TimeUnit.SECONDS);
391
392 assertEquals(limit, avgLimiter.getAvailable());
393
394
395 assertTrue(avgLimiter.canExecute(guessNumber));
396 avgLimiter.consume(guessNumber);
397
398
399 assertTrue((limit - guessNumber) == avgLimiter.getAvailable());
400
401
402
403 avgLimiter.consume(-80);
404 assertTrue((limit - guessNumber + 80) == avgLimiter.getAvailable());
405
406
407 avgLimiter.consume(-80);
408 assertTrue(limit == avgLimiter.getAvailable());
409
410 }
411 }