21
21
import java .util .Optional ;
22
22
import java .util .concurrent .CompletableFuture ;
23
23
import java .util .concurrent .TimeUnit ;
24
+ import java .util .function .Supplier ;
24
25
import org .apache .pulsar .broker .ServiceConfiguration ;
25
- import org .apache .pulsar .broker .qos .AsyncTokenBucket ;
26
- import org .apache .pulsar .broker .qos .AsyncTokenBucketBuilder ;
27
26
import org .apache .pulsar .broker .service .BrokerService ;
28
27
import org .apache .pulsar .common .naming .NamespaceName ;
29
28
import org .apache .pulsar .common .naming .TopicName ;
30
29
import org .apache .pulsar .common .policies .data .DispatchRate ;
31
30
import org .apache .pulsar .common .policies .data .Policies ;
31
+ import org .apache .pulsar .common .util .RateLimiter ;
32
32
import org .slf4j .Logger ;
33
33
import org .slf4j .LoggerFactory ;
34
34
@@ -46,8 +46,8 @@ public enum Type {
46
46
private final Type type ;
47
47
48
48
private final BrokerService brokerService ;
49
- private volatile AsyncTokenBucket dispatchRateLimiterOnMessage ;
50
- private volatile AsyncTokenBucket dispatchRateLimiterOnByte ;
49
+ private volatile RateLimiter dispatchRateLimiterOnMessage ;
50
+ private volatile RateLimiter dispatchRateLimiterOnByte ;
51
51
52
52
public DispatchRateLimiter (PersistentTopic topic , Type type ) {
53
53
this (topic , null , type );
@@ -77,9 +77,9 @@ public DispatchRateLimiter(BrokerService brokerService) {
77
77
* @return
78
78
*/
79
79
public long getAvailableDispatchRateLimitOnMsg () {
80
- AsyncTokenBucket localDispatchRateLimiterOnMessage = dispatchRateLimiterOnMessage ;
80
+ RateLimiter localDispatchRateLimiterOnMessage = dispatchRateLimiterOnMessage ;
81
81
return localDispatchRateLimiterOnMessage == null ? -1 :
82
- Math .max (localDispatchRateLimiterOnMessage .getTokens (), 0 );
82
+ Math .max (localDispatchRateLimiterOnMessage .getAvailablePermits (), 0 );
83
83
}
84
84
85
85
/**
@@ -88,8 +88,9 @@ public long getAvailableDispatchRateLimitOnMsg() {
88
88
* @return
89
89
*/
90
90
public long getAvailableDispatchRateLimitOnByte () {
91
- AsyncTokenBucket localDispatchRateLimiterOnByte = dispatchRateLimiterOnByte ;
92
- return localDispatchRateLimiterOnByte == null ? -1 : Math .max (localDispatchRateLimiterOnByte .getTokens (), 0 );
91
+ RateLimiter localDispatchRateLimiterOnByte = dispatchRateLimiterOnByte ;
92
+ return localDispatchRateLimiterOnByte == null ? -1 :
93
+ Math .max (localDispatchRateLimiterOnByte .getAvailablePermits (), 0 );
93
94
}
94
95
95
96
/**
@@ -99,13 +100,13 @@ public long getAvailableDispatchRateLimitOnByte() {
99
100
* @param byteSize
100
101
*/
101
102
public void consumeDispatchQuota (long numberOfMessages , long byteSize ) {
102
- AsyncTokenBucket localDispatchRateLimiterOnMessage = dispatchRateLimiterOnMessage ;
103
+ RateLimiter localDispatchRateLimiterOnMessage = dispatchRateLimiterOnMessage ;
103
104
if (numberOfMessages > 0 && localDispatchRateLimiterOnMessage != null ) {
104
- localDispatchRateLimiterOnMessage .consumeTokens (numberOfMessages );
105
+ localDispatchRateLimiterOnMessage .tryAcquire (numberOfMessages );
105
106
}
106
- AsyncTokenBucket localDispatchRateLimiterOnByte = dispatchRateLimiterOnByte ;
107
+ RateLimiter localDispatchRateLimiterOnByte = dispatchRateLimiterOnByte ;
107
108
if (byteSize > 0 && localDispatchRateLimiterOnByte != null ) {
108
- localDispatchRateLimiterOnByte .consumeTokens (byteSize );
109
+ localDispatchRateLimiterOnByte .tryAcquire (byteSize );
109
110
}
110
111
}
111
112
@@ -221,50 +222,63 @@ public synchronized void updateDispatchRate(DispatchRate dispatchRate) {
221
222
222
223
long msgRate = dispatchRate .getDispatchThrottlingRateInMsg ();
223
224
long byteRate = dispatchRate .getDispatchThrottlingRateInByte ();
224
- long ratePeriodNanos = TimeUnit . SECONDS . toNanos ( Math . max ( dispatchRate .getRatePeriodInSecond (), 1 ) );
225
+ long ratePeriod = dispatchRate .getRatePeriodInSecond ();
225
226
227
+ Supplier <Long > permitUpdaterMsg = dispatchRate .isRelativeToPublishRate ()
228
+ ? () -> getRelativeDispatchRateInMsg (dispatchRate )
229
+ : null ;
226
230
// update msg-rateLimiter
227
231
if (msgRate > 0 ) {
228
- if (dispatchRate . isRelativeToPublishRate () ) {
232
+ if (this . dispatchRateLimiterOnMessage == null ) {
229
233
this .dispatchRateLimiterOnMessage =
230
- configureAsyncTokenBucket (AsyncTokenBucket .builderForDynamicRate ())
231
- .rateFunction (() -> getRelativeDispatchRateInMsg (dispatchRate ))
232
- .ratePeriodNanosFunction (() -> ratePeriodNanos )
234
+ RateLimiter .builder ()
235
+ .scheduledExecutorService (brokerService .pulsar ().getExecutor ())
236
+ .permits (msgRate )
237
+ .rateTime (ratePeriod )
238
+ .timeUnit (TimeUnit .SECONDS )
239
+ .permitUpdater (permitUpdaterMsg )
240
+ .isDispatchOrPrecisePublishRateLimiter (true )
233
241
.build ();
234
242
} else {
235
- this .dispatchRateLimiterOnMessage =
236
- configureAsyncTokenBucket (AsyncTokenBucket .builder ())
237
- .rate (msgRate ).ratePeriodNanos (ratePeriodNanos )
238
- .build ();
243
+ this .dispatchRateLimiterOnMessage .setRate (msgRate , dispatchRate .getRatePeriodInSecond (),
244
+ TimeUnit .SECONDS , permitUpdaterMsg );
239
245
}
240
246
} else {
241
- this .dispatchRateLimiterOnMessage = null ;
247
+ // message-rate should be disable and close
248
+ if (this .dispatchRateLimiterOnMessage != null ) {
249
+ this .dispatchRateLimiterOnMessage .close ();
250
+ this .dispatchRateLimiterOnMessage = null ;
251
+ }
242
252
}
243
253
254
+ Supplier <Long > permitUpdaterByte = dispatchRate .isRelativeToPublishRate ()
255
+ ? () -> getRelativeDispatchRateInByte (dispatchRate )
256
+ : null ;
244
257
// update byte-rateLimiter
245
258
if (byteRate > 0 ) {
246
- if (dispatchRate . isRelativeToPublishRate () ) {
259
+ if (this . dispatchRateLimiterOnByte == null ) {
247
260
this .dispatchRateLimiterOnByte =
248
- configureAsyncTokenBucket (AsyncTokenBucket .builderForDynamicRate ())
249
- .rateFunction (() -> getRelativeDispatchRateInByte (dispatchRate ))
250
- .ratePeriodNanosFunction (() -> ratePeriodNanos )
261
+ RateLimiter .builder ()
262
+ .scheduledExecutorService (brokerService .pulsar ().getExecutor ())
263
+ .permits (byteRate )
264
+ .rateTime (ratePeriod )
265
+ .timeUnit (TimeUnit .SECONDS )
266
+ .permitUpdater (permitUpdaterByte )
267
+ .isDispatchOrPrecisePublishRateLimiter (true )
251
268
.build ();
252
269
} else {
253
- this .dispatchRateLimiterOnByte =
254
- configureAsyncTokenBucket (AsyncTokenBucket .builder ())
255
- .rate (byteRate ).ratePeriodNanos (ratePeriodNanos )
256
- .build ();
270
+ this .dispatchRateLimiterOnByte .setRate (byteRate , dispatchRate .getRatePeriodInSecond (),
271
+ TimeUnit .SECONDS , permitUpdaterByte );
257
272
}
258
273
} else {
259
- this .dispatchRateLimiterOnByte = null ;
274
+ // message-rate should be disable and close
275
+ if (this .dispatchRateLimiterOnByte != null ) {
276
+ this .dispatchRateLimiterOnByte .close ();
277
+ this .dispatchRateLimiterOnByte = null ;
278
+ }
260
279
}
261
280
}
262
281
263
- private <T extends AsyncTokenBucketBuilder <T >> T configureAsyncTokenBucket (T builder ) {
264
- builder .clock (brokerService .getPulsar ().getMonotonicSnapshotClock ());
265
- return builder ;
266
- }
267
-
268
282
private long getRelativeDispatchRateInMsg (DispatchRate dispatchRate ) {
269
283
return (topic != null && dispatchRate != null )
270
284
? (long ) topic .getLastUpdatedAvgPublishRateInMsg () + dispatchRate .getDispatchThrottlingRateInMsg ()
@@ -283,7 +297,7 @@ private long getRelativeDispatchRateInByte(DispatchRate dispatchRate) {
283
297
* @return
284
298
*/
285
299
public long getDispatchRateOnMsg () {
286
- AsyncTokenBucket localDispatchRateLimiterOnMessage = dispatchRateLimiterOnMessage ;
300
+ RateLimiter localDispatchRateLimiterOnMessage = dispatchRateLimiterOnMessage ;
287
301
return localDispatchRateLimiterOnMessage != null ? localDispatchRateLimiterOnMessage .getRate () : -1 ;
288
302
}
289
303
@@ -293,7 +307,7 @@ public long getDispatchRateOnMsg() {
293
307
* @return
294
308
*/
295
309
public long getDispatchRateOnByte () {
296
- AsyncTokenBucket localDispatchRateLimiterOnByte = dispatchRateLimiterOnByte ;
310
+ RateLimiter localDispatchRateLimiterOnByte = dispatchRateLimiterOnByte ;
297
311
return localDispatchRateLimiterOnByte != null ? localDispatchRateLimiterOnByte .getRate () : -1 ;
298
312
}
299
313
@@ -306,9 +320,11 @@ public static boolean isDispatchRateEnabled(DispatchRate dispatchRate) {
306
320
public void close () {
307
321
// close rate-limiter
308
322
if (dispatchRateLimiterOnMessage != null ) {
323
+ dispatchRateLimiterOnMessage .close ();
309
324
dispatchRateLimiterOnMessage = null ;
310
325
}
311
326
if (dispatchRateLimiterOnByte != null ) {
327
+ dispatchRateLimiterOnByte .close ();
312
328
dispatchRateLimiterOnByte = null ;
313
329
}
314
330
}
0 commit comments