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
;
21 import org
.apache
.hadoop
.conf
.Configuration
;
22 import org
.apache
.yetus
.audience
.InterfaceAudience
;
23 import org
.apache
.yetus
.audience
.InterfaceStability
;
24 import org
.slf4j
.Logger
;
25 import org
.slf4j
.LoggerFactory
;
28 * Internal class used to check and consume quota if exceed throttle quota is enabled. Exceed
29 * throttle quota means, user can over consume user/namespace/table quota if region server has
30 * additional available quota because other users don't consume at the same time.
32 * There are some limits when enable exceed throttle quota:
33 * 1. Must set at least one read and one write region server throttle quota;
34 * 2. All region server throttle quotas must be in seconds time unit. Because once previous requests
35 * exceed their quota and consume region server quota, quota in other time units may be refilled in
36 * a long time, this may affect later requests.
38 @InterfaceAudience.Private
39 @InterfaceStability.Evolving
40 public class ExceedOperationQuota
extends DefaultOperationQuota
{
41 private static final Logger LOG
= LoggerFactory
.getLogger(ExceedOperationQuota
.class);
42 private QuotaLimiter regionServerLimiter
;
44 public ExceedOperationQuota(final Configuration conf
, QuotaLimiter regionServerLimiter
,
45 final QuotaLimiter
... limiters
) {
46 super(conf
, limiters
);
47 this.regionServerLimiter
= regionServerLimiter
;
51 public void checkQuota(int numWrites
, int numReads
, int numScans
) throws RpcThrottlingException
{
52 if (regionServerLimiter
.isBypass()) {
53 // If region server limiter is bypass, which means no region server quota is set, check and
54 // throttle by all other quotas. In this condition, exceed throttle quota will not work.
55 LOG
.warn("Exceed throttle quota is enabled but no region server quotas found");
56 super.checkQuota(numWrites
, numReads
, numScans
);
58 // 1. Update estimate quota which will be consumed
59 updateEstimateConsumeQuota(numWrites
, numReads
, numScans
);
60 // 2. Check if region server limiter is enough. If not, throw RpcThrottlingException.
61 regionServerLimiter
.checkQuota(numWrites
, writeConsumed
, numReads
+ numScans
, readConsumed
,
62 writeCapacityUnitConsumed
, readCapacityUnitConsumed
);
63 // 3. Check if other limiters are enough. If not, exceed other limiters because region server
65 boolean exceed
= false;
67 super.checkQuota(numWrites
, numReads
, numScans
);
68 } catch (RpcThrottlingException e
) {
70 if (LOG
.isDebugEnabled()) {
71 LOG
.debug("Read/Write requests num exceeds quota: writes:{} reads:{} scan:{}, "
72 + "try use region server quota",
73 numWrites
, numReads
, numScans
);
76 // 4. Region server limiter is enough and grab estimated consume quota.
77 readAvailable
= Math
.max(readAvailable
, regionServerLimiter
.getReadAvailable());
78 regionServerLimiter
.grabQuota(numWrites
, writeConsumed
, numReads
+ numScans
, readConsumed
,
79 writeCapacityUnitConsumed
, writeCapacityUnitConsumed
);
81 // 5. Other quota limiter is exceeded and has not been grabbed (because throw
82 // RpcThrottlingException in Step 3), so grab it.
83 for (final QuotaLimiter limiter
: limiters
) {
84 limiter
.grabQuota(numWrites
, writeConsumed
, numReads
+ numScans
, readConsumed
,
85 writeCapacityUnitConsumed
, writeCapacityUnitConsumed
);
95 regionServerLimiter
.consumeWrite(writeDiff
, writeCapacityUnitDiff
);
98 regionServerLimiter
.consumeRead(readDiff
, readCapacityUnitDiff
);