2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 package org
.apache
.hadoop
.hbase
.quotas
;
22 import org
.apache
.hadoop
.conf
.Configuration
;
23 import org
.apache
.hadoop
.hbase
.HBaseConfiguration
;
24 import org
.apache
.yetus
.audience
.InterfaceAudience
;
25 import org
.apache
.yetus
.audience
.InterfaceStability
;
26 import org
.apache
.hadoop
.hbase
.shaded
.protobuf
.ProtobufUtil
;
27 import org
.apache
.hadoop
.hbase
.shaded
.protobuf
.generated
.QuotaProtos
.Throttle
;
28 import org
.apache
.hadoop
.hbase
.shaded
.protobuf
.generated
.QuotaProtos
.TimedQuota
;
31 * Simple time based limiter that checks the quota Throttle
33 @InterfaceAudience.Private
34 @InterfaceStability.Evolving
35 public class TimeBasedLimiter
implements QuotaLimiter
{
36 private static final Configuration conf
= HBaseConfiguration
.create();
37 private RateLimiter reqsLimiter
= null;
38 private RateLimiter reqSizeLimiter
= null;
39 private RateLimiter writeReqsLimiter
= null;
40 private RateLimiter writeSizeLimiter
= null;
41 private RateLimiter readReqsLimiter
= null;
42 private RateLimiter readSizeLimiter
= null;
43 private RateLimiter reqCapacityUnitLimiter
= null;
44 private RateLimiter writeCapacityUnitLimiter
= null;
45 private RateLimiter readCapacityUnitLimiter
= null;
47 private TimeBasedLimiter() {
48 if (FixedIntervalRateLimiter
.class.getName().equals(
49 conf
.getClass(RateLimiter
.QUOTA_RATE_LIMITER_CONF_KEY
, AverageIntervalRateLimiter
.class)
51 reqsLimiter
= new FixedIntervalRateLimiter();
52 reqSizeLimiter
= new FixedIntervalRateLimiter();
53 writeReqsLimiter
= new FixedIntervalRateLimiter();
54 writeSizeLimiter
= new FixedIntervalRateLimiter();
55 readReqsLimiter
= new FixedIntervalRateLimiter();
56 readSizeLimiter
= new FixedIntervalRateLimiter();
57 reqCapacityUnitLimiter
= new FixedIntervalRateLimiter();
58 writeCapacityUnitLimiter
= new FixedIntervalRateLimiter();
59 readCapacityUnitLimiter
= new FixedIntervalRateLimiter();
61 reqsLimiter
= new AverageIntervalRateLimiter();
62 reqSizeLimiter
= new AverageIntervalRateLimiter();
63 writeReqsLimiter
= new AverageIntervalRateLimiter();
64 writeSizeLimiter
= new AverageIntervalRateLimiter();
65 readReqsLimiter
= new AverageIntervalRateLimiter();
66 readSizeLimiter
= new AverageIntervalRateLimiter();
67 reqCapacityUnitLimiter
= new AverageIntervalRateLimiter();
68 writeCapacityUnitLimiter
= new AverageIntervalRateLimiter();
69 readCapacityUnitLimiter
= new AverageIntervalRateLimiter();
73 static QuotaLimiter
fromThrottle(final Throttle throttle
) {
74 TimeBasedLimiter limiter
= new TimeBasedLimiter();
75 boolean isBypass
= true;
76 if (throttle
.hasReqNum()) {
77 setFromTimedQuota(limiter
.reqsLimiter
, throttle
.getReqNum());
81 if (throttle
.hasReqSize()) {
82 setFromTimedQuota(limiter
.reqSizeLimiter
, throttle
.getReqSize());
86 if (throttle
.hasWriteNum()) {
87 setFromTimedQuota(limiter
.writeReqsLimiter
, throttle
.getWriteNum());
91 if (throttle
.hasWriteSize()) {
92 setFromTimedQuota(limiter
.writeSizeLimiter
, throttle
.getWriteSize());
96 if (throttle
.hasReadNum()) {
97 setFromTimedQuota(limiter
.readReqsLimiter
, throttle
.getReadNum());
101 if (throttle
.hasReadSize()) {
102 setFromTimedQuota(limiter
.readSizeLimiter
, throttle
.getReadSize());
106 if (throttle
.hasReqCapacityUnit()) {
107 setFromTimedQuota(limiter
.reqCapacityUnitLimiter
, throttle
.getReqCapacityUnit());
111 if (throttle
.hasWriteCapacityUnit()) {
112 setFromTimedQuota(limiter
.writeCapacityUnitLimiter
, throttle
.getWriteCapacityUnit());
116 if (throttle
.hasReadCapacityUnit()) {
117 setFromTimedQuota(limiter
.readCapacityUnitLimiter
, throttle
.getReadCapacityUnit());
120 return isBypass ? NoopQuotaLimiter
.get() : limiter
;
123 public void update(final TimeBasedLimiter other
) {
124 reqsLimiter
.update(other
.reqsLimiter
);
125 reqSizeLimiter
.update(other
.reqSizeLimiter
);
126 writeReqsLimiter
.update(other
.writeReqsLimiter
);
127 writeSizeLimiter
.update(other
.writeSizeLimiter
);
128 readReqsLimiter
.update(other
.readReqsLimiter
);
129 readSizeLimiter
.update(other
.readSizeLimiter
);
130 reqCapacityUnitLimiter
.update(other
.reqCapacityUnitLimiter
);
131 writeCapacityUnitLimiter
.update(other
.writeCapacityUnitLimiter
);
132 readCapacityUnitLimiter
.update(other
.readCapacityUnitLimiter
);
135 private static void setFromTimedQuota(final RateLimiter limiter
, final TimedQuota timedQuota
) {
136 limiter
.set(timedQuota
.getSoftLimit(), ProtobufUtil
.toTimeUnit(timedQuota
.getTimeUnit()));
140 public void checkQuota(long writeReqs
, long estimateWriteSize
, long readReqs
,
141 long estimateReadSize
, long estimateWriteCapacityUnit
, long estimateReadCapacityUnit
)
142 throws RpcThrottlingException
{
143 if (!reqsLimiter
.canExecute(writeReqs
+ readReqs
)) {
144 RpcThrottlingException
.throwNumRequestsExceeded(reqsLimiter
.waitInterval());
146 if (!reqSizeLimiter
.canExecute(estimateWriteSize
+ estimateReadSize
)) {
147 RpcThrottlingException
.throwRequestSizeExceeded(
148 reqSizeLimiter
.waitInterval(estimateWriteSize
+ estimateReadSize
));
150 if (!reqCapacityUnitLimiter
.canExecute(estimateWriteCapacityUnit
+ estimateReadCapacityUnit
)) {
151 RpcThrottlingException
.throwRequestCapacityUnitExceeded(
152 reqCapacityUnitLimiter
.waitInterval(estimateWriteCapacityUnit
+ estimateReadCapacityUnit
));
155 if (estimateWriteSize
> 0) {
156 if (!writeReqsLimiter
.canExecute(writeReqs
)) {
157 RpcThrottlingException
.throwNumWriteRequestsExceeded(writeReqsLimiter
.waitInterval());
159 if (!writeSizeLimiter
.canExecute(estimateWriteSize
)) {
160 RpcThrottlingException
.throwWriteSizeExceeded(
161 writeSizeLimiter
.waitInterval(estimateWriteSize
));
163 if (!writeCapacityUnitLimiter
.canExecute(estimateWriteCapacityUnit
)) {
164 RpcThrottlingException
.throwWriteCapacityUnitExceeded(
165 writeCapacityUnitLimiter
.waitInterval(estimateWriteCapacityUnit
));
169 if (estimateReadSize
> 0) {
170 if (!readReqsLimiter
.canExecute(readReqs
)) {
171 RpcThrottlingException
.throwNumReadRequestsExceeded(readReqsLimiter
.waitInterval());
173 if (!readSizeLimiter
.canExecute(estimateReadSize
)) {
174 RpcThrottlingException
.throwReadSizeExceeded(
175 readSizeLimiter
.waitInterval(estimateReadSize
));
177 if (!readCapacityUnitLimiter
.canExecute(estimateReadCapacityUnit
)) {
178 RpcThrottlingException
.throwReadCapacityUnitExceeded(
179 readCapacityUnitLimiter
.waitInterval(estimateReadCapacityUnit
));
185 public void grabQuota(long writeReqs
, long writeSize
, long readReqs
, long readSize
,
186 long writeCapacityUnit
, long readCapacityUnit
) {
187 assert writeSize
!= 0 || readSize
!= 0;
189 reqsLimiter
.consume(writeReqs
+ readReqs
);
190 reqSizeLimiter
.consume(writeSize
+ readSize
);
193 writeReqsLimiter
.consume(writeReqs
);
194 writeSizeLimiter
.consume(writeSize
);
197 readReqsLimiter
.consume(readReqs
);
198 readSizeLimiter
.consume(readSize
);
200 if (writeCapacityUnit
> 0) {
201 reqCapacityUnitLimiter
.consume(writeCapacityUnit
);
202 writeCapacityUnitLimiter
.consume(writeCapacityUnit
);
204 if (readCapacityUnit
> 0) {
205 reqCapacityUnitLimiter
.consume(readCapacityUnit
);
206 readCapacityUnitLimiter
.consume(readCapacityUnit
);
211 public void consumeWrite(final long size
, long capacityUnit
) {
212 reqSizeLimiter
.consume(size
);
213 writeSizeLimiter
.consume(size
);
214 reqCapacityUnitLimiter
.consume(capacityUnit
);
215 writeCapacityUnitLimiter
.consume(capacityUnit
);
219 public void consumeRead(final long size
, long capacityUnit
) {
220 reqSizeLimiter
.consume(size
);
221 readSizeLimiter
.consume(size
);
222 reqCapacityUnitLimiter
.consume(capacityUnit
);
223 readCapacityUnitLimiter
.consume(capacityUnit
);
227 public boolean isBypass() {
232 public long getWriteAvailable() {
233 return writeSizeLimiter
.getAvailable();
237 public long getReadAvailable() {
238 return readSizeLimiter
.getAvailable();
242 public String
toString() {
243 StringBuilder builder
= new StringBuilder();
244 builder
.append("TimeBasedLimiter(");
245 if (!reqsLimiter
.isBypass()) {
246 builder
.append("reqs=" + reqsLimiter
);
248 if (!reqSizeLimiter
.isBypass()) {
249 builder
.append(" resSize=" + reqSizeLimiter
);
251 if (!writeReqsLimiter
.isBypass()) {
252 builder
.append(" writeReqs=" + writeReqsLimiter
);
254 if (!writeSizeLimiter
.isBypass()) {
255 builder
.append(" writeSize=" + writeSizeLimiter
);
257 if (!readReqsLimiter
.isBypass()) {
258 builder
.append(" readReqs=" + readReqsLimiter
);
260 if (!readSizeLimiter
.isBypass()) {
261 builder
.append(" readSize=" + readSizeLimiter
);
263 if (!reqCapacityUnitLimiter
.isBypass()) {
264 builder
.append(" reqCapacityUnit=" + reqCapacityUnitLimiter
);
266 if (!writeCapacityUnitLimiter
.isBypass()) {
267 builder
.append(" writeCapacityUnit=" + writeCapacityUnitLimiter
);
269 if (!readCapacityUnitLimiter
.isBypass()) {
270 builder
.append(" readCapacityUnit=" + readCapacityUnitLimiter
);
273 return builder
.toString();