HBASE-21820 Implement CLUSTER quota scope
Signed-off-by: Guanghao Zhang <zghao@apache.org>
This commit is contained in:
parent
b1c42f1009
commit
9370347efe
|
@ -203,7 +203,21 @@ public class QuotaSettingsFactory {
|
||||||
*/
|
*/
|
||||||
public static QuotaSettings throttleUser(final String userName, final ThrottleType type,
|
public static QuotaSettings throttleUser(final String userName, final ThrottleType type,
|
||||||
final long limit, final TimeUnit timeUnit) {
|
final long limit, final TimeUnit timeUnit) {
|
||||||
return throttle(userName, null, null, null, type, limit, timeUnit);
|
return throttleUser(userName, type, limit, timeUnit, QuotaScope.MACHINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throttle the specified user.
|
||||||
|
* @param userName the user to throttle
|
||||||
|
* @param type the type of throttling
|
||||||
|
* @param limit the allowed number of request/data per timeUnit
|
||||||
|
* @param timeUnit the limit time unit
|
||||||
|
* @param scope the scope of throttling
|
||||||
|
* @return the quota settings
|
||||||
|
*/
|
||||||
|
public static QuotaSettings throttleUser(final String userName, final ThrottleType type,
|
||||||
|
final long limit, final TimeUnit timeUnit, QuotaScope scope) {
|
||||||
|
return throttle(userName, null, null, null, type, limit, timeUnit, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -218,7 +232,22 @@ public class QuotaSettingsFactory {
|
||||||
*/
|
*/
|
||||||
public static QuotaSettings throttleUser(final String userName, final TableName tableName,
|
public static QuotaSettings throttleUser(final String userName, final TableName tableName,
|
||||||
final ThrottleType type, final long limit, final TimeUnit timeUnit) {
|
final ThrottleType type, final long limit, final TimeUnit timeUnit) {
|
||||||
return throttle(userName, tableName, null, null, type, limit, timeUnit);
|
return throttleUser(userName, tableName, type, limit, timeUnit, QuotaScope.MACHINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throttle the specified user on the specified table.
|
||||||
|
* @param userName the user to throttle
|
||||||
|
* @param tableName the table to throttle
|
||||||
|
* @param type the type of throttling
|
||||||
|
* @param limit the allowed number of request/data per timeUnit
|
||||||
|
* @param timeUnit the limit time unit
|
||||||
|
* @param scope the scope of throttling
|
||||||
|
* @return the quota settings
|
||||||
|
*/
|
||||||
|
public static QuotaSettings throttleUser(final String userName, final TableName tableName,
|
||||||
|
final ThrottleType type, final long limit, final TimeUnit timeUnit, QuotaScope scope) {
|
||||||
|
return throttle(userName, tableName, null, null, type, limit, timeUnit, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -233,7 +262,22 @@ public class QuotaSettingsFactory {
|
||||||
*/
|
*/
|
||||||
public static QuotaSettings throttleUser(final String userName, final String namespace,
|
public static QuotaSettings throttleUser(final String userName, final String namespace,
|
||||||
final ThrottleType type, final long limit, final TimeUnit timeUnit) {
|
final ThrottleType type, final long limit, final TimeUnit timeUnit) {
|
||||||
return throttle(userName, null, namespace, null, type, limit, timeUnit);
|
return throttleUser(userName, namespace, type, limit, timeUnit, QuotaScope.MACHINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throttle the specified user on the specified namespace.
|
||||||
|
* @param userName the user to throttle
|
||||||
|
* @param namespace the namespace to throttle
|
||||||
|
* @param type the type of throttling
|
||||||
|
* @param limit the allowed number of request/data per timeUnit
|
||||||
|
* @param timeUnit the limit time unit
|
||||||
|
* @param scope the scope of throttling
|
||||||
|
* @return the quota settings
|
||||||
|
*/
|
||||||
|
public static QuotaSettings throttleUser(final String userName, final String namespace,
|
||||||
|
final ThrottleType type, final long limit, final TimeUnit timeUnit, QuotaScope scope) {
|
||||||
|
return throttle(userName, null, namespace, null, type, limit, timeUnit, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -243,7 +287,7 @@ public class QuotaSettingsFactory {
|
||||||
* @return the quota settings
|
* @return the quota settings
|
||||||
*/
|
*/
|
||||||
public static QuotaSettings unthrottleUser(final String userName) {
|
public static QuotaSettings unthrottleUser(final String userName) {
|
||||||
return throttle(userName, null, null, null, null, 0, null);
|
return throttle(userName, null, null, null, null, 0, null, QuotaScope.MACHINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -254,7 +298,7 @@ public class QuotaSettingsFactory {
|
||||||
* @return the quota settings
|
* @return the quota settings
|
||||||
*/
|
*/
|
||||||
public static QuotaSettings unthrottleUser(final String userName, final TableName tableName) {
|
public static QuotaSettings unthrottleUser(final String userName, final TableName tableName) {
|
||||||
return throttle(userName, tableName, null, null, null, 0, null);
|
return throttle(userName, tableName, null, null, null, 0, null, QuotaScope.MACHINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -265,7 +309,7 @@ public class QuotaSettingsFactory {
|
||||||
* @return the quota settings
|
* @return the quota settings
|
||||||
*/
|
*/
|
||||||
public static QuotaSettings unthrottleUser(final String userName, final String namespace) {
|
public static QuotaSettings unthrottleUser(final String userName, final String namespace) {
|
||||||
return throttle(userName, null, namespace, null, null, 0, null);
|
return throttle(userName, null, namespace, null, null, 0, null, QuotaScope.MACHINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -279,7 +323,21 @@ public class QuotaSettingsFactory {
|
||||||
*/
|
*/
|
||||||
public static QuotaSettings throttleTable(final TableName tableName, final ThrottleType type,
|
public static QuotaSettings throttleTable(final TableName tableName, final ThrottleType type,
|
||||||
final long limit, final TimeUnit timeUnit) {
|
final long limit, final TimeUnit timeUnit) {
|
||||||
return throttle(null, tableName, null, null, type, limit, timeUnit);
|
return throttleTable(tableName, type, limit, timeUnit, QuotaScope.MACHINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throttle the specified table.
|
||||||
|
* @param tableName the table to throttle
|
||||||
|
* @param type the type of throttling
|
||||||
|
* @param limit the allowed number of request/data per timeUnit
|
||||||
|
* @param timeUnit the limit time unit
|
||||||
|
* @param scope the scope of throttling
|
||||||
|
* @return the quota settings
|
||||||
|
*/
|
||||||
|
public static QuotaSettings throttleTable(final TableName tableName, final ThrottleType type,
|
||||||
|
final long limit, final TimeUnit timeUnit, QuotaScope scope) {
|
||||||
|
return throttle(null, tableName, null, null, type, limit, timeUnit, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -289,7 +347,7 @@ public class QuotaSettingsFactory {
|
||||||
* @return the quota settings
|
* @return the quota settings
|
||||||
*/
|
*/
|
||||||
public static QuotaSettings unthrottleTable(final TableName tableName) {
|
public static QuotaSettings unthrottleTable(final TableName tableName) {
|
||||||
return throttle(null, tableName, null, null, null, 0, null);
|
return throttle(null, tableName, null, null, null, 0, null, QuotaScope.MACHINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -303,7 +361,21 @@ public class QuotaSettingsFactory {
|
||||||
*/
|
*/
|
||||||
public static QuotaSettings throttleNamespace(final String namespace, final ThrottleType type,
|
public static QuotaSettings throttleNamespace(final String namespace, final ThrottleType type,
|
||||||
final long limit, final TimeUnit timeUnit) {
|
final long limit, final TimeUnit timeUnit) {
|
||||||
return throttle(null, null, namespace, null, type, limit, timeUnit);
|
return throttleNamespace(namespace, type, limit, timeUnit, QuotaScope.MACHINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throttle the specified namespace.
|
||||||
|
* @param namespace the namespace to throttle
|
||||||
|
* @param type the type of throttling
|
||||||
|
* @param limit the allowed number of request/data per timeUnit
|
||||||
|
* @param timeUnit the limit time unit
|
||||||
|
* @param scope the scope of throttling
|
||||||
|
* @return the quota settings
|
||||||
|
*/
|
||||||
|
public static QuotaSettings throttleNamespace(final String namespace, final ThrottleType type,
|
||||||
|
final long limit, final TimeUnit timeUnit, QuotaScope scope) {
|
||||||
|
return throttle(null, null, namespace, null, type, limit, timeUnit, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -313,7 +385,7 @@ public class QuotaSettingsFactory {
|
||||||
* @return the quota settings
|
* @return the quota settings
|
||||||
*/
|
*/
|
||||||
public static QuotaSettings unthrottleNamespace(final String namespace) {
|
public static QuotaSettings unthrottleNamespace(final String namespace) {
|
||||||
return throttle(null, null, namespace, null, null, 0, null);
|
return throttle(null, null, namespace, null, null, 0, null, QuotaScope.MACHINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -327,7 +399,7 @@ public class QuotaSettingsFactory {
|
||||||
*/
|
*/
|
||||||
public static QuotaSettings throttleRegionServer(final String regionServer,
|
public static QuotaSettings throttleRegionServer(final String regionServer,
|
||||||
final ThrottleType type, final long limit, final TimeUnit timeUnit) {
|
final ThrottleType type, final long limit, final TimeUnit timeUnit) {
|
||||||
return throttle(null, null, null, regionServer, type, limit, timeUnit);
|
return throttle(null, null, null, regionServer, type, limit, timeUnit, QuotaScope.MACHINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -337,19 +409,19 @@ public class QuotaSettingsFactory {
|
||||||
* @return the quota settings
|
* @return the quota settings
|
||||||
*/
|
*/
|
||||||
public static QuotaSettings unthrottleRegionServer(final String regionServer) {
|
public static QuotaSettings unthrottleRegionServer(final String regionServer) {
|
||||||
return throttle(null, null, null, regionServer, null, 0, null);
|
return throttle(null, null, null, regionServer, null, 0, null, QuotaScope.MACHINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Throttle helper */
|
/* Throttle helper */
|
||||||
private static QuotaSettings throttle(final String userName, final TableName tableName,
|
private static QuotaSettings throttle(final String userName, final TableName tableName,
|
||||||
final String namespace, final String regionServer, final ThrottleType type, final long limit,
|
final String namespace, final String regionServer, final ThrottleType type, final long limit,
|
||||||
final TimeUnit timeUnit) {
|
final TimeUnit timeUnit, QuotaScope scope) {
|
||||||
QuotaProtos.ThrottleRequest.Builder builder = QuotaProtos.ThrottleRequest.newBuilder();
|
QuotaProtos.ThrottleRequest.Builder builder = QuotaProtos.ThrottleRequest.newBuilder();
|
||||||
if (type != null) {
|
if (type != null) {
|
||||||
builder.setType(ProtobufUtil.toProtoThrottleType(type));
|
builder.setType(ProtobufUtil.toProtoThrottleType(type));
|
||||||
}
|
}
|
||||||
if (timeUnit != null) {
|
if (timeUnit != null) {
|
||||||
builder.setTimedQuota(ProtobufUtil.toTimedQuota(limit, timeUnit, QuotaScope.MACHINE));
|
builder.setTimedQuota(ProtobufUtil.toTimedQuota(limit, timeUnit, scope));
|
||||||
}
|
}
|
||||||
return new ThrottleSettings(userName, tableName, namespace, regionServer, builder.build());
|
return new ThrottleSettings(userName, tableName, namespace, regionServer, builder.build());
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,14 @@ package org.apache.hadoop.hbase.quotas;
|
||||||
|
|
||||||
import static org.apache.hadoop.hbase.util.ConcurrentMapUtils.computeIfAbsent;
|
import static org.apache.hadoop.hbase.util.ConcurrentMapUtils.computeIfAbsent;
|
||||||
|
|
||||||
|
import org.apache.hadoop.hbase.ClusterMetrics.Option;
|
||||||
|
import org.apache.hadoop.hbase.MetaTableAccessor;
|
||||||
import org.apache.hadoop.hbase.regionserver.HRegionServer;
|
import org.apache.hadoop.hbase.regionserver.HRegionServer;
|
||||||
import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting;
|
import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -72,6 +75,10 @@ public class QuotaCache implements Stoppable {
|
||||||
private final ConcurrentHashMap<String, QuotaState> regionServerQuotaCache =
|
private final ConcurrentHashMap<String, QuotaState> regionServerQuotaCache =
|
||||||
new ConcurrentHashMap<>();
|
new ConcurrentHashMap<>();
|
||||||
private volatile boolean exceedThrottleQuotaEnabled = false;
|
private volatile boolean exceedThrottleQuotaEnabled = false;
|
||||||
|
// factors used to divide cluster scope quota into machine scope quota
|
||||||
|
private volatile double machineQuotaFactor = 1;
|
||||||
|
private final ConcurrentHashMap<TableName, Double> tableMachineQuotaFactors =
|
||||||
|
new ConcurrentHashMap<>();
|
||||||
private final RegionServerServices rsServices;
|
private final RegionServerServices rsServices;
|
||||||
|
|
||||||
private QuotaRefresherChore refreshChore;
|
private QuotaRefresherChore refreshChore;
|
||||||
|
@ -228,6 +235,7 @@ public class QuotaCache implements Stoppable {
|
||||||
QuotaCache.this.regionServerQuotaCache.putIfAbsent(QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY,
|
QuotaCache.this.regionServerQuotaCache.putIfAbsent(QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY,
|
||||||
new QuotaState());
|
new QuotaState());
|
||||||
|
|
||||||
|
updateQuotaFactors();
|
||||||
fetchNamespaceQuotaState();
|
fetchNamespaceQuotaState();
|
||||||
fetchTableQuotaState();
|
fetchTableQuotaState();
|
||||||
fetchUserQuotaState();
|
fetchUserQuotaState();
|
||||||
|
@ -246,7 +254,8 @@ public class QuotaCache implements Stoppable {
|
||||||
@Override
|
@Override
|
||||||
public Map<String, QuotaState> fetchEntries(final List<Get> gets)
|
public Map<String, QuotaState> fetchEntries(final List<Get> gets)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
return QuotaUtil.fetchNamespaceQuotas(rsServices.getConnection(), gets);
|
return QuotaUtil.fetchNamespaceQuotas(rsServices.getConnection(), gets,
|
||||||
|
machineQuotaFactor);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -261,7 +270,8 @@ public class QuotaCache implements Stoppable {
|
||||||
@Override
|
@Override
|
||||||
public Map<TableName, QuotaState> fetchEntries(final List<Get> gets)
|
public Map<TableName, QuotaState> fetchEntries(final List<Get> gets)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
return QuotaUtil.fetchTableQuotas(rsServices.getConnection(), gets);
|
return QuotaUtil.fetchTableQuotas(rsServices.getConnection(), gets,
|
||||||
|
tableMachineQuotaFactors);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -278,7 +288,8 @@ public class QuotaCache implements Stoppable {
|
||||||
@Override
|
@Override
|
||||||
public Map<String, UserQuotaState> fetchEntries(final List<Get> gets)
|
public Map<String, UserQuotaState> fetchEntries(final List<Get> gets)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
return QuotaUtil.fetchUserQuotas(rsServices.getConnection(), gets);
|
return QuotaUtil.fetchUserQuotas(rsServices.getConnection(), gets,
|
||||||
|
tableMachineQuotaFactors, machineQuotaFactor);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -351,6 +362,46 @@ public class QuotaCache implements Stoppable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update quota factors which is used to divide cluster scope quota into machine scope quota
|
||||||
|
*
|
||||||
|
* For user/namespace/user over namespace quota, use [1 / RSNum] as machine factor.
|
||||||
|
* For table/user over table quota, use [1 / TotalTableRegionNum * MachineTableRegionNum]
|
||||||
|
* as machine factor.
|
||||||
|
*/
|
||||||
|
private void updateQuotaFactors() {
|
||||||
|
// Update machine quota factor
|
||||||
|
try {
|
||||||
|
int rsSize = rsServices.getConnection().getAdmin()
|
||||||
|
.getClusterMetrics(EnumSet.of(Option.SERVERS_NAME)).getServersName().size();
|
||||||
|
if (rsSize != 0) {
|
||||||
|
// TODO if use rs group, the cluster limit should be shared by the rs group
|
||||||
|
machineQuotaFactor = 1.0 / rsSize;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.warn("Get live region servers failed", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update table machine quota factors
|
||||||
|
for (TableName tableName : tableQuotaCache.keySet()) {
|
||||||
|
double factor = 1;
|
||||||
|
try {
|
||||||
|
long regionSize =
|
||||||
|
MetaTableAccessor.getTableRegions(rsServices.getConnection(), tableName, true)
|
||||||
|
.stream().filter(regionInfo -> !regionInfo.isOffline()).count();
|
||||||
|
if (regionSize == 0) {
|
||||||
|
factor = 0;
|
||||||
|
} else {
|
||||||
|
int localRegionSize = rsServices.getRegions(tableName).size();
|
||||||
|
factor = 1.0 * localRegionSize / regionSize;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.warn("Get table regions failed: {}", tableName, e);
|
||||||
|
}
|
||||||
|
tableMachineQuotaFactors.put(tableName, factor);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static interface Fetcher<Key, Value> {
|
static interface Fetcher<Key, Value> {
|
||||||
|
|
|
@ -48,6 +48,7 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.TimeUnit;
|
import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.TimeUnit;
|
||||||
|
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.QuotaScope;
|
||||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.Quotas;
|
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.Quotas;
|
||||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.Throttle;
|
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.Throttle;
|
||||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.TimedQuota;
|
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.TimedQuota;
|
||||||
|
@ -266,7 +267,8 @@ public class QuotaUtil extends QuotaTableUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, UserQuotaState> fetchUserQuotas(final Connection connection,
|
public static Map<String, UserQuotaState> fetchUserQuotas(final Connection connection,
|
||||||
final List<Get> gets) throws IOException {
|
final List<Get> gets, Map<TableName, Double> tableMachineQuotaFactors, double factor)
|
||||||
|
throws IOException {
|
||||||
long nowTs = EnvironmentEdgeManager.currentTime();
|
long nowTs = EnvironmentEdgeManager.currentTime();
|
||||||
Result[] results = doGet(connection, gets);
|
Result[] results = doGet(connection, gets);
|
||||||
|
|
||||||
|
@ -286,16 +288,21 @@ public class QuotaUtil extends QuotaTableUtil {
|
||||||
parseUserResult(user, results[i], new UserQuotasVisitor() {
|
parseUserResult(user, results[i], new UserQuotasVisitor() {
|
||||||
@Override
|
@Override
|
||||||
public void visitUserQuotas(String userName, String namespace, Quotas quotas) {
|
public void visitUserQuotas(String userName, String namespace, Quotas quotas) {
|
||||||
|
quotas = updateClusterQuotaToMachineQuota(quotas, factor);
|
||||||
quotaInfo.setQuotas(namespace, quotas);
|
quotaInfo.setQuotas(namespace, quotas);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitUserQuotas(String userName, TableName table, Quotas quotas) {
|
public void visitUserQuotas(String userName, TableName table, Quotas quotas) {
|
||||||
|
quotas = updateClusterQuotaToMachineQuota(quotas,
|
||||||
|
tableMachineQuotaFactors.containsKey(table) ? tableMachineQuotaFactors.get(table)
|
||||||
|
: 1);
|
||||||
quotaInfo.setQuotas(table, quotas);
|
quotaInfo.setQuotas(table, quotas);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitUserQuotas(String userName, Quotas quotas) {
|
public void visitUserQuotas(String userName, Quotas quotas) {
|
||||||
|
quotas = updateClusterQuotaToMachineQuota(quotas, factor);
|
||||||
quotaInfo.setQuotas(quotas);
|
quotaInfo.setQuotas(quotas);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -308,24 +315,34 @@ public class QuotaUtil extends QuotaTableUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<TableName, QuotaState> fetchTableQuotas(final Connection connection,
|
public static Map<TableName, QuotaState> fetchTableQuotas(final Connection connection,
|
||||||
final List<Get> gets) throws IOException {
|
final List<Get> gets, Map<TableName, Double> tableMachineFactors) throws IOException {
|
||||||
return fetchGlobalQuotas("table", connection, gets, new KeyFromRow<TableName>() {
|
return fetchGlobalQuotas("table", connection, gets, new KeyFromRow<TableName>() {
|
||||||
@Override
|
@Override
|
||||||
public TableName getKeyFromRow(final byte[] row) {
|
public TableName getKeyFromRow(final byte[] row) {
|
||||||
assert isTableRowKey(row);
|
assert isTableRowKey(row);
|
||||||
return getTableFromRowKey(row);
|
return getTableFromRowKey(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getFactor(TableName tableName) {
|
||||||
|
return tableMachineFactors.containsKey(tableName) ? tableMachineFactors.get(tableName) : 1;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, QuotaState> fetchNamespaceQuotas(final Connection connection,
|
public static Map<String, QuotaState> fetchNamespaceQuotas(final Connection connection,
|
||||||
final List<Get> gets) throws IOException {
|
final List<Get> gets, double factor) throws IOException {
|
||||||
return fetchGlobalQuotas("namespace", connection, gets, new KeyFromRow<String>() {
|
return fetchGlobalQuotas("namespace", connection, gets, new KeyFromRow<String>() {
|
||||||
@Override
|
@Override
|
||||||
public String getKeyFromRow(final byte[] row) {
|
public String getKeyFromRow(final byte[] row) {
|
||||||
assert isNamespaceRowKey(row);
|
assert isNamespaceRowKey(row);
|
||||||
return getNamespaceFromRowKey(row);
|
return getNamespaceFromRowKey(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getFactor(String s) {
|
||||||
|
return factor;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,6 +354,11 @@ public class QuotaUtil extends QuotaTableUtil {
|
||||||
assert isRegionServerRowKey(row);
|
assert isRegionServerRowKey(row);
|
||||||
return getRegionServerFromRowKey(row);
|
return getRegionServerFromRowKey(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getFactor(String s) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,6 +384,8 @@ public class QuotaUtil extends QuotaTableUtil {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Quotas quotas = quotasFromData(data);
|
Quotas quotas = quotasFromData(data);
|
||||||
|
quotas = updateClusterQuotaToMachineQuota(quotas,
|
||||||
|
kfr.getFactor(key));
|
||||||
quotaInfo.setQuotas(quotas);
|
quotaInfo.setQuotas(quotas);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Unable to parse " + type + " '" + key + "' quotas", e);
|
LOG.error("Unable to parse " + type + " '" + key + "' quotas", e);
|
||||||
|
@ -371,8 +395,62 @@ public class QuotaUtil extends QuotaTableUtil {
|
||||||
return globalQuotas;
|
return globalQuotas;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert cluster scope quota to machine scope quota
|
||||||
|
* @param quotas the original quota
|
||||||
|
* @param factor factor used to divide cluster limiter to machine limiter
|
||||||
|
* @return the converted quota whose quota limiters all in machine scope
|
||||||
|
*/
|
||||||
|
private static Quotas updateClusterQuotaToMachineQuota(Quotas quotas, double factor) {
|
||||||
|
Quotas.Builder newQuotas = Quotas.newBuilder(quotas);
|
||||||
|
if (newQuotas.hasThrottle()) {
|
||||||
|
Throttle.Builder throttle = Throttle.newBuilder(newQuotas.getThrottle());
|
||||||
|
if (throttle.hasReqNum()) {
|
||||||
|
throttle.setReqNum(updateTimedQuota(throttle.getReqNum(), factor));
|
||||||
|
}
|
||||||
|
if (throttle.hasReqSize()) {
|
||||||
|
throttle.setReqSize(updateTimedQuota(throttle.getReqSize(), factor));
|
||||||
|
}
|
||||||
|
if (throttle.hasReadNum()) {
|
||||||
|
throttle.setReadNum(updateTimedQuota(throttle.getReadNum(), factor));
|
||||||
|
}
|
||||||
|
if (throttle.hasReadSize()) {
|
||||||
|
throttle.setReadSize(updateTimedQuota(throttle.getReadSize(), factor));
|
||||||
|
}
|
||||||
|
if (throttle.hasWriteNum()) {
|
||||||
|
throttle.setWriteNum(updateTimedQuota(throttle.getWriteNum(), factor));
|
||||||
|
}
|
||||||
|
if (throttle.hasWriteSize()) {
|
||||||
|
throttle.setWriteSize(updateTimedQuota(throttle.getWriteSize(), factor));
|
||||||
|
}
|
||||||
|
if (throttle.hasReqCapacityUnit()) {
|
||||||
|
throttle.setReqCapacityUnit(updateTimedQuota(throttle.getReqCapacityUnit(), factor));
|
||||||
|
}
|
||||||
|
if (throttle.hasReadCapacityUnit()) {
|
||||||
|
throttle.setReadCapacityUnit(updateTimedQuota(throttle.getReadCapacityUnit(), factor));
|
||||||
|
}
|
||||||
|
if (throttle.hasWriteCapacityUnit()) {
|
||||||
|
throttle.setWriteCapacityUnit(updateTimedQuota(throttle.getWriteCapacityUnit(), factor));
|
||||||
|
}
|
||||||
|
newQuotas.setThrottle(throttle.build());
|
||||||
|
}
|
||||||
|
return newQuotas.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TimedQuota updateTimedQuota(TimedQuota timedQuota, double factor) {
|
||||||
|
if (timedQuota.getScope() == QuotaScope.CLUSTER) {
|
||||||
|
TimedQuota.Builder newTimedQuota = TimedQuota.newBuilder(timedQuota);
|
||||||
|
newTimedQuota.setSoftLimit(Math.max(1, (long) (timedQuota.getSoftLimit() * factor)))
|
||||||
|
.setScope(QuotaScope.MACHINE);
|
||||||
|
return newTimedQuota.build();
|
||||||
|
} else {
|
||||||
|
return timedQuota;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static interface KeyFromRow<T> {
|
private static interface KeyFromRow<T> {
|
||||||
T getKeyFromRow(final byte[] row);
|
T getKeyFromRow(final byte[] row);
|
||||||
|
double getFactor(T t);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* =========================================================================
|
/* =========================================================================
|
||||||
|
|
|
@ -0,0 +1,236 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.hadoop.hbase.quotas;
|
||||||
|
|
||||||
|
import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.doGets;
|
||||||
|
import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.doPuts;
|
||||||
|
import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.triggerNamespaceCacheRefresh;
|
||||||
|
import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.triggerTableCacheRefresh;
|
||||||
|
import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.triggerUserCacheRefresh;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.apache.hadoop.hbase.HBaseClassTestRule;
|
||||||
|
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
||||||
|
import org.apache.hadoop.hbase.HConstants;
|
||||||
|
import org.apache.hadoop.hbase.NamespaceDescriptor;
|
||||||
|
import org.apache.hadoop.hbase.TableName;
|
||||||
|
import org.apache.hadoop.hbase.client.Admin;
|
||||||
|
import org.apache.hadoop.hbase.client.Table;
|
||||||
|
import org.apache.hadoop.hbase.security.User;
|
||||||
|
import org.apache.hadoop.hbase.testclassification.LargeTests;
|
||||||
|
import org.apache.hadoop.hbase.testclassification.RegionServerTests;
|
||||||
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
|
import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
|
||||||
|
import org.apache.hadoop.hbase.util.JVMClusterUtil.RegionServerThread;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.experimental.categories.Category;
|
||||||
|
|
||||||
|
@Category({ RegionServerTests.class, LargeTests.class })
|
||||||
|
public class TestClusterScopeQuotaThrottle {
|
||||||
|
|
||||||
|
@ClassRule
|
||||||
|
public static final HBaseClassTestRule CLASS_RULE =
|
||||||
|
HBaseClassTestRule.forClass(TestClusterScopeQuotaThrottle.class);
|
||||||
|
|
||||||
|
private final static int REFRESH_TIME = 30 * 60000;
|
||||||
|
private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
|
||||||
|
|
||||||
|
private final static TableName[] TABLE_NAMES =
|
||||||
|
new TableName[] { TableName.valueOf("TestQuotaAdmin0"), TableName.valueOf("TestQuotaAdmin1"),
|
||||||
|
TableName.valueOf("TestQuotaAdmin2") };
|
||||||
|
private final static byte[] FAMILY = Bytes.toBytes("cf");
|
||||||
|
private final static byte[] QUALIFIER = Bytes.toBytes("q");
|
||||||
|
private final static byte[][] SPLITS = new byte[][] { Bytes.toBytes("1") };
|
||||||
|
private static Table[] tables;
|
||||||
|
|
||||||
|
private final static String NAMESPACE = "TestNs";
|
||||||
|
private final static TableName TABLE_NAME = TableName.valueOf(NAMESPACE, "TestTable");
|
||||||
|
private static Table table;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUpBeforeClass() throws Exception {
|
||||||
|
TEST_UTIL.getConfiguration().setBoolean(QuotaUtil.QUOTA_CONF_KEY, true);
|
||||||
|
TEST_UTIL.getConfiguration().setInt(QuotaCache.REFRESH_CONF_KEY, REFRESH_TIME);
|
||||||
|
TEST_UTIL.getConfiguration().setInt("hbase.hstore.compactionThreshold", 10);
|
||||||
|
TEST_UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", 100);
|
||||||
|
TEST_UTIL.getConfiguration().setInt("hbase.client.pause", 250);
|
||||||
|
TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 6);
|
||||||
|
TEST_UTIL.getConfiguration().setBoolean("hbase.master.enabletable.roundrobin", true);
|
||||||
|
TEST_UTIL.startMiniCluster(2);
|
||||||
|
TEST_UTIL.waitTableAvailable(QuotaTableUtil.QUOTA_TABLE_NAME);
|
||||||
|
QuotaCache.TEST_FORCE_REFRESH = true;
|
||||||
|
|
||||||
|
tables = new Table[TABLE_NAMES.length];
|
||||||
|
for (int i = 0; i < TABLE_NAMES.length; ++i) {
|
||||||
|
tables[i] = TEST_UTIL.createTable(TABLE_NAMES[i], FAMILY);
|
||||||
|
TEST_UTIL.waitTableAvailable(TABLE_NAMES[i]);
|
||||||
|
}
|
||||||
|
TEST_UTIL.getAdmin().createNamespace(NamespaceDescriptor.create(NAMESPACE).build());
|
||||||
|
table = TEST_UTIL.createTable(TABLE_NAME, FAMILY, SPLITS);
|
||||||
|
TEST_UTIL.waitTableAvailable(TABLE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void tearDownAfterClass() throws Exception {
|
||||||
|
EnvironmentEdgeManager.reset();
|
||||||
|
for (int i = 0; i < tables.length; ++i) {
|
||||||
|
if (tables[i] != null) {
|
||||||
|
tables[i].close();
|
||||||
|
TEST_UTIL.deleteTable(TABLE_NAMES[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TEST_UTIL.deleteTable(TABLE_NAME);
|
||||||
|
TEST_UTIL.getAdmin().deleteNamespace(NAMESPACE);
|
||||||
|
TEST_UTIL.shutdownMiniCluster();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
ThrottleQuotaTestUtil.clearQuotaCache(TEST_UTIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNamespaceClusterScopeQuota() throws Exception {
|
||||||
|
final Admin admin = TEST_UTIL.getAdmin();
|
||||||
|
final String NAMESPACE = "default";
|
||||||
|
|
||||||
|
// Add 10req/min limit for write request in cluster scope
|
||||||
|
admin.setQuota(QuotaSettingsFactory.throttleNamespace(NAMESPACE, ThrottleType.WRITE_NUMBER, 10,
|
||||||
|
TimeUnit.MINUTES, QuotaScope.CLUSTER));
|
||||||
|
// Add 6req/min limit for read request in machine scope
|
||||||
|
admin.setQuota(QuotaSettingsFactory.throttleNamespace(NAMESPACE, ThrottleType.READ_NUMBER, 6,
|
||||||
|
TimeUnit.MINUTES, QuotaScope.MACHINE));
|
||||||
|
triggerNamespaceCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
|
// should execute at max 5 write requests and at max 3 read requests
|
||||||
|
assertEquals(5, doPuts(10, FAMILY, QUALIFIER, tables[0]));
|
||||||
|
assertEquals(6, doGets(10, tables[0]));
|
||||||
|
// Remove all the limits
|
||||||
|
admin.setQuota(QuotaSettingsFactory.unthrottleNamespace(NAMESPACE));
|
||||||
|
triggerNamespaceCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTableClusterScopeQuota() throws Exception {
|
||||||
|
final Admin admin = TEST_UTIL.getAdmin();
|
||||||
|
admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAME, ThrottleType.READ_NUMBER, 20,
|
||||||
|
TimeUnit.HOURS, QuotaScope.CLUSTER));
|
||||||
|
triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAME);
|
||||||
|
for (RegionServerThread rst : TEST_UTIL.getMiniHBaseCluster().getRegionServerThreads()) {
|
||||||
|
for (TableName tableName : rst.getRegionServer().getOnlineTables()) {
|
||||||
|
if (tableName.getNameAsString().equals(TABLE_NAME.getNameAsString())) {
|
||||||
|
int rsRegionNum = rst.getRegionServer().getRegions(tableName).size();
|
||||||
|
if (rsRegionNum == 0) {
|
||||||
|
// If rs has 0 region, the machine limiter is 0 (20 * 0 / 2)
|
||||||
|
break;
|
||||||
|
} else if (rsRegionNum == 1) {
|
||||||
|
// If rs has 1 region, the machine limiter is 10 (20 * 1 / 2)
|
||||||
|
// Read rows from 1 region, so can read 10 first time and 0 second time
|
||||||
|
long count = doGets(20, table);
|
||||||
|
assertTrue(count == 0 || count == 10);
|
||||||
|
} else if (rsRegionNum == 2) {
|
||||||
|
// If rs has 2 regions, the machine limiter is 20 (20 * 2 / 2)
|
||||||
|
assertEquals(20, doGets(20, table));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAME));
|
||||||
|
triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUserClusterScopeQuota() throws Exception {
|
||||||
|
final Admin admin = TEST_UTIL.getAdmin();
|
||||||
|
final String userName = User.getCurrent().getShortName();
|
||||||
|
|
||||||
|
// Add 6req/min limit for read request in cluster scope
|
||||||
|
admin.setQuota(QuotaSettingsFactory.throttleUser(userName, ThrottleType.READ_NUMBER, 6,
|
||||||
|
TimeUnit.MINUTES, QuotaScope.CLUSTER));
|
||||||
|
// Add 6req/min limit for write request in machine scope
|
||||||
|
admin.setQuota(
|
||||||
|
QuotaSettingsFactory.throttleUser(userName, ThrottleType.WRITE_NUMBER, 6, TimeUnit.MINUTES));
|
||||||
|
triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES);
|
||||||
|
// should execute at max 6 read requests and at max 3 write write requests
|
||||||
|
assertEquals(6, doPuts(10, FAMILY, QUALIFIER, tables[0]));
|
||||||
|
assertEquals(3, doGets(10, tables[0]));
|
||||||
|
// Remove all the limits
|
||||||
|
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName));
|
||||||
|
triggerUserCacheRefresh(TEST_UTIL, true, TABLE_NAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUserNamespaceClusterScopeQuota() throws Exception {
|
||||||
|
final Admin admin = TEST_UTIL.getAdmin();
|
||||||
|
final String userName = User.getCurrent().getShortName();
|
||||||
|
final String namespace = TABLE_NAMES[0].getNamespaceAsString();
|
||||||
|
|
||||||
|
// Add 10req/min limit for read request in cluster scope
|
||||||
|
admin.setQuota(QuotaSettingsFactory.throttleUser(userName, namespace, ThrottleType.READ_NUMBER,
|
||||||
|
10, TimeUnit.MINUTES, QuotaScope.CLUSTER));
|
||||||
|
// Add 6req/min limit for write request in machine scope
|
||||||
|
admin.setQuota(QuotaSettingsFactory.throttleUser(userName, namespace, ThrottleType.WRITE_NUMBER,
|
||||||
|
6, TimeUnit.MINUTES));
|
||||||
|
triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
|
// should execute at max 5 read requests and at max 6 write requests
|
||||||
|
assertEquals(5, doGets(10, tables[0]));
|
||||||
|
assertEquals(6, doPuts(10, FAMILY, QUALIFIER, tables[0]));
|
||||||
|
|
||||||
|
// Remove all the limits
|
||||||
|
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName, namespace));
|
||||||
|
triggerUserCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUserTableClusterScopeQuota() throws Exception {
|
||||||
|
final Admin admin = TEST_UTIL.getAdmin();
|
||||||
|
final String userName = User.getCurrent().getShortName();
|
||||||
|
admin.setQuota(QuotaSettingsFactory.throttleUser(userName, TABLE_NAME, ThrottleType.READ_NUMBER,
|
||||||
|
20, TimeUnit.HOURS, QuotaScope.CLUSTER));
|
||||||
|
triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAME);
|
||||||
|
for (RegionServerThread rst : TEST_UTIL.getMiniHBaseCluster().getRegionServerThreads()) {
|
||||||
|
for (TableName tableName : rst.getRegionServer().getOnlineTables()) {
|
||||||
|
if (tableName.getNameAsString().equals(TABLE_NAME.getNameAsString())) {
|
||||||
|
int rsRegionNum = rst.getRegionServer().getRegions(tableName).size();
|
||||||
|
if (rsRegionNum == 0) {
|
||||||
|
// If rs has 0 region, the machine limiter is 0 (20 * 0 / 2)
|
||||||
|
break;
|
||||||
|
} else if (rsRegionNum == 1) {
|
||||||
|
// If rs has 1 region, the machine limiter is 10 (20 * 1 / 2)
|
||||||
|
// Read rows from 1 region, so can read 10 first time and 0 second time
|
||||||
|
long count = doGets(20, table);
|
||||||
|
assertTrue(count == 0 || count == 10);
|
||||||
|
} else if (rsRegionNum == 2) {
|
||||||
|
// If rs has 2 regions, the machine limiter is 20 (20 * 2 / 2)
|
||||||
|
assertEquals(20, doGets(20, table));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName));
|
||||||
|
triggerUserCacheRefresh(TEST_UTIL, true, TABLE_NAME);
|
||||||
|
}
|
||||||
|
}
|
|
@ -639,6 +639,57 @@ public class TestQuotaAdmin {
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleRegionServer(regionServer));
|
admin.setQuota(QuotaSettingsFactory.unthrottleRegionServer(regionServer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQuotaScope() throws Exception {
|
||||||
|
Admin admin = TEST_UTIL.getAdmin();
|
||||||
|
String user = "user1";
|
||||||
|
String namespace = "testQuotaScope_ns";
|
||||||
|
TableName tableName = TableName.valueOf("testQuotaScope");
|
||||||
|
QuotaFilter filter = new QuotaFilter();
|
||||||
|
|
||||||
|
// set CLUSTER quota scope for namespace
|
||||||
|
admin.setQuota(QuotaSettingsFactory.throttleNamespace(namespace, ThrottleType.REQUEST_NUMBER,
|
||||||
|
10, TimeUnit.MINUTES, QuotaScope.CLUSTER));
|
||||||
|
assertNumResults(1, filter);
|
||||||
|
verifyRecordPresentInQuotaTable(ThrottleType.REQUEST_NUMBER, 10, TimeUnit.MINUTES,
|
||||||
|
QuotaScope.CLUSTER);
|
||||||
|
admin.setQuota(QuotaSettingsFactory.throttleNamespace(namespace, ThrottleType.REQUEST_NUMBER,
|
||||||
|
10, TimeUnit.MINUTES, QuotaScope.MACHINE));
|
||||||
|
assertNumResults(1, filter);
|
||||||
|
verifyRecordPresentInQuotaTable(ThrottleType.REQUEST_NUMBER, 10, TimeUnit.MINUTES,
|
||||||
|
QuotaScope.MACHINE);
|
||||||
|
admin.setQuota(QuotaSettingsFactory.unthrottleNamespace(namespace));
|
||||||
|
assertNumResults(0, filter);
|
||||||
|
|
||||||
|
// set CLUSTER quota scope for table
|
||||||
|
admin.setQuota(QuotaSettingsFactory.throttleTable(tableName, ThrottleType.REQUEST_NUMBER, 10,
|
||||||
|
TimeUnit.MINUTES, QuotaScope.CLUSTER));
|
||||||
|
verifyRecordPresentInQuotaTable(ThrottleType.REQUEST_NUMBER, 10, TimeUnit.MINUTES,
|
||||||
|
QuotaScope.CLUSTER);
|
||||||
|
admin.setQuota(QuotaSettingsFactory.unthrottleTable(tableName));
|
||||||
|
|
||||||
|
// set CLUSTER quota scope for user
|
||||||
|
admin.setQuota(QuotaSettingsFactory.throttleUser(user, ThrottleType.REQUEST_NUMBER, 10,
|
||||||
|
TimeUnit.MINUTES, QuotaScope.CLUSTER));
|
||||||
|
verifyRecordPresentInQuotaTable(ThrottleType.REQUEST_NUMBER, 10, TimeUnit.MINUTES,
|
||||||
|
QuotaScope.CLUSTER);
|
||||||
|
admin.setQuota(QuotaSettingsFactory.unthrottleUser(user));
|
||||||
|
|
||||||
|
// set CLUSTER quota scope for user and table
|
||||||
|
admin.setQuota(QuotaSettingsFactory.throttleUser(user, tableName, ThrottleType.REQUEST_NUMBER,
|
||||||
|
10, TimeUnit.MINUTES, QuotaScope.CLUSTER));
|
||||||
|
verifyRecordPresentInQuotaTable(ThrottleType.REQUEST_NUMBER, 10, TimeUnit.MINUTES,
|
||||||
|
QuotaScope.CLUSTER);
|
||||||
|
admin.setQuota(QuotaSettingsFactory.unthrottleUser(user));
|
||||||
|
|
||||||
|
// set CLUSTER quota scope for user and namespace
|
||||||
|
admin.setQuota(QuotaSettingsFactory.throttleUser(user, namespace, ThrottleType.REQUEST_NUMBER,
|
||||||
|
10, TimeUnit.MINUTES, QuotaScope.CLUSTER));
|
||||||
|
verifyRecordPresentInQuotaTable(ThrottleType.REQUEST_NUMBER, 10, TimeUnit.MINUTES,
|
||||||
|
QuotaScope.CLUSTER);
|
||||||
|
admin.setQuota(QuotaSettingsFactory.unthrottleUser(user));
|
||||||
|
}
|
||||||
|
|
||||||
private void testSwitchRpcThrottle(Admin admin, boolean oldRpcThrottle, boolean newRpcThrottle)
|
private void testSwitchRpcThrottle(Admin admin, boolean oldRpcThrottle, boolean newRpcThrottle)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
boolean state = admin.switchRpcThrottle(newRpcThrottle);
|
boolean state = admin.switchRpcThrottle(newRpcThrottle);
|
||||||
|
@ -651,13 +702,18 @@ public class TestQuotaAdmin {
|
||||||
|
|
||||||
private void verifyRecordPresentInQuotaTable(ThrottleType type, long limit, TimeUnit tu)
|
private void verifyRecordPresentInQuotaTable(ThrottleType type, long limit, TimeUnit tu)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
verifyRecordPresentInQuotaTable(type, limit, tu, QuotaScope.MACHINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyRecordPresentInQuotaTable(ThrottleType type, long limit, TimeUnit tu,
|
||||||
|
QuotaScope scope) throws Exception {
|
||||||
// Verify the RPC Quotas in the table
|
// Verify the RPC Quotas in the table
|
||||||
try (Table quotaTable = TEST_UTIL.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME);
|
try (Table quotaTable = TEST_UTIL.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME);
|
||||||
ResultScanner scanner = quotaTable.getScanner(new Scan())) {
|
ResultScanner scanner = quotaTable.getScanner(new Scan())) {
|
||||||
Result r = Iterables.getOnlyElement(scanner);
|
Result r = Iterables.getOnlyElement(scanner);
|
||||||
CellScanner cells = r.cellScanner();
|
CellScanner cells = r.cellScanner();
|
||||||
assertTrue("Expected to find a cell", cells.advance());
|
assertTrue("Expected to find a cell", cells.advance());
|
||||||
assertRPCQuota(type, limit, tu, cells.current());
|
assertRPCQuota(type, limit, tu, scope, cells.current());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,8 +740,8 @@ public class TestQuotaAdmin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertRPCQuota(ThrottleType type, long limit, TimeUnit tu, Cell cell)
|
private void assertRPCQuota(ThrottleType type, long limit, TimeUnit tu, QuotaScope scope,
|
||||||
throws Exception {
|
Cell cell) throws Exception {
|
||||||
Quotas q = QuotaTableUtil
|
Quotas q = QuotaTableUtil
|
||||||
.quotasFromData(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
|
.quotasFromData(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
|
||||||
assertTrue("Quota should have rpc quota defined", q.hasThrottle());
|
assertTrue("Quota should have rpc quota defined", q.hasThrottle());
|
||||||
|
@ -733,6 +789,7 @@ public class TestQuotaAdmin {
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assertEquals(scope, ProtobufUtil.toQuotaScope(t.getScope()));
|
||||||
assertEquals(t.getSoftLimit(), limit);
|
assertEquals(t.getSoftLimit(), limit);
|
||||||
assertEquals(t.getTimeUnit(), ProtobufUtil.toProtoTimeUnit(tu));
|
assertEquals(t.getTimeUnit(), ProtobufUtil.toProtoTimeUnit(tu));
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,16 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.hadoop.hbase.quotas;
|
package org.apache.hadoop.hbase.quotas;
|
||||||
|
|
||||||
|
import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.doGets;
|
||||||
|
import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.doPuts;
|
||||||
|
import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.triggerExceedThrottleQuotaCacheRefresh;
|
||||||
|
import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.triggerNamespaceCacheRefresh;
|
||||||
|
import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.triggerRegionServerCacheRefresh;
|
||||||
|
import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.triggerTableCacheRefresh;
|
||||||
|
import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.triggerUserCacheRefresh;
|
||||||
|
import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.waitMinuteQuota;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import org.apache.hadoop.hbase.HBaseClassTestRule;
|
import org.apache.hadoop.hbase.HBaseClassTestRule;
|
||||||
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
||||||
|
@ -27,16 +34,12 @@ import org.apache.hadoop.hbase.HConstants;
|
||||||
import org.apache.hadoop.hbase.TableName;
|
import org.apache.hadoop.hbase.TableName;
|
||||||
import org.apache.hadoop.hbase.client.Admin;
|
import org.apache.hadoop.hbase.client.Admin;
|
||||||
import org.apache.hadoop.hbase.client.Get;
|
import org.apache.hadoop.hbase.client.Get;
|
||||||
import org.apache.hadoop.hbase.client.Put;
|
|
||||||
import org.apache.hadoop.hbase.client.Table;
|
import org.apache.hadoop.hbase.client.Table;
|
||||||
import org.apache.hadoop.hbase.security.User;
|
import org.apache.hadoop.hbase.security.User;
|
||||||
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
||||||
import org.apache.hadoop.hbase.testclassification.RegionServerTests;
|
import org.apache.hadoop.hbase.testclassification.RegionServerTests;
|
||||||
import org.apache.hadoop.hbase.util.Bytes;
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
|
import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
|
||||||
import org.apache.hadoop.hbase.util.EnvironmentEdgeManagerTestHelper;
|
|
||||||
import org.apache.hadoop.hbase.util.JVMClusterUtil.RegionServerThread;
|
|
||||||
import org.apache.hadoop.hbase.util.ManualEnvironmentEdge;
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
@ -68,8 +71,6 @@ public class TestQuotaThrottle {
|
||||||
TableName.valueOf("TestQuotaAdmin1"),
|
TableName.valueOf("TestQuotaAdmin1"),
|
||||||
TableName.valueOf("TestQuotaAdmin2")
|
TableName.valueOf("TestQuotaAdmin2")
|
||||||
};
|
};
|
||||||
|
|
||||||
private static ManualEnvironmentEdge envEdge;
|
|
||||||
private static Table[] tables;
|
private static Table[] tables;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
|
@ -89,10 +90,6 @@ public class TestQuotaThrottle {
|
||||||
for (int i = 0; i < TABLE_NAMES.length; ++i) {
|
for (int i = 0; i < TABLE_NAMES.length; ++i) {
|
||||||
tables[i] = TEST_UTIL.createTable(TABLE_NAMES[i], FAMILY);
|
tables[i] = TEST_UTIL.createTable(TABLE_NAMES[i], FAMILY);
|
||||||
}
|
}
|
||||||
|
|
||||||
envEdge = new ManualEnvironmentEdge();
|
|
||||||
envEdge.setValue(EnvironmentEdgeManager.currentTime());
|
|
||||||
EnvironmentEdgeManagerTestHelper.injectEdge(envEdge);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
|
@ -110,13 +107,7 @@ public class TestQuotaThrottle {
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
for (RegionServerThread rst: TEST_UTIL.getMiniHBaseCluster().getRegionServerThreads()) {
|
ThrottleQuotaTestUtil.clearQuotaCache(TEST_UTIL);
|
||||||
RegionServerRpcQuotaManager quotaManager = rst.getRegionServer().getRegionServerRpcQuotaManager();
|
|
||||||
QuotaCache quotaCache = quotaManager.getQuotaCache();
|
|
||||||
quotaCache.getNamespaceQuotaCache().clear();
|
|
||||||
quotaCache.getTableQuotaCache().clear();
|
|
||||||
quotaCache.getUserQuotaCache().clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -125,21 +116,21 @@ public class TestQuotaThrottle {
|
||||||
final String userName = User.getCurrent().getShortName();
|
final String userName = User.getCurrent().getShortName();
|
||||||
|
|
||||||
// Add 6req/min limit
|
// Add 6req/min limit
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(QuotaSettingsFactory.throttleUser(userName, ThrottleType.REQUEST_NUMBER, 6,
|
||||||
.throttleUser(userName, ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
|
TimeUnit.MINUTES));
|
||||||
triggerUserCacheRefresh(false, TABLE_NAMES);
|
triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES);
|
||||||
|
|
||||||
// should execute at max 6 requests
|
// should execute at max 6 requests
|
||||||
assertEquals(6, doPuts(100, tables));
|
assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables));
|
||||||
|
|
||||||
// wait a minute and you should get other 6 requests executed
|
// wait a minute and you should get other 6 requests executed
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
assertEquals(6, doPuts(100, tables));
|
assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables));
|
||||||
|
|
||||||
// Remove all the limits
|
// Remove all the limits
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName));
|
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName));
|
||||||
triggerUserCacheRefresh(true, TABLE_NAMES);
|
triggerUserCacheRefresh(TEST_UTIL, true, TABLE_NAMES);
|
||||||
assertEquals(60, doPuts(60, tables));
|
assertEquals(60, doPuts(60, FAMILY, QUALIFIER, tables));
|
||||||
assertEquals(60, doGets(60, tables));
|
assertEquals(60, doGets(60, tables));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,29 +140,29 @@ public class TestQuotaThrottle {
|
||||||
final String userName = User.getCurrent().getShortName();
|
final String userName = User.getCurrent().getShortName();
|
||||||
|
|
||||||
// Add 6req/min limit for read request
|
// Add 6req/min limit for read request
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(
|
||||||
.throttleUser(userName, ThrottleType.READ_NUMBER, 6, TimeUnit.MINUTES));
|
QuotaSettingsFactory.throttleUser(userName, ThrottleType.READ_NUMBER, 6, TimeUnit.MINUTES));
|
||||||
triggerUserCacheRefresh(false, TABLE_NAMES);
|
triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES);
|
||||||
|
|
||||||
// not limit for write request and should execute at max 6 read requests
|
// not limit for write request and should execute at max 6 read requests
|
||||||
assertEquals(60, doPuts(60, tables));
|
assertEquals(60, doPuts(60, FAMILY, QUALIFIER, tables));
|
||||||
assertEquals(6, doGets(100, tables));
|
assertEquals(6, doGets(100, tables));
|
||||||
|
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
|
|
||||||
// Add 6req/min limit for write request
|
// Add 6req/min limit for write request
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(
|
||||||
.throttleUser(userName, ThrottleType.WRITE_NUMBER, 6, TimeUnit.MINUTES));
|
QuotaSettingsFactory.throttleUser(userName, ThrottleType.WRITE_NUMBER, 6, TimeUnit.MINUTES));
|
||||||
triggerUserCacheRefresh(false, TABLE_NAMES);
|
triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES);
|
||||||
|
|
||||||
// should execute at max 6 read requests and at max 6 write write requests
|
// should execute at max 6 read requests and at max 6 write write requests
|
||||||
assertEquals(6, doGets(100, tables));
|
assertEquals(6, doGets(100, tables));
|
||||||
assertEquals(6, doPuts(60, tables));
|
assertEquals(6, doPuts(60, FAMILY, QUALIFIER, tables));
|
||||||
|
|
||||||
// Remove all the limits
|
// Remove all the limits
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName));
|
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName));
|
||||||
triggerUserCacheRefresh(true, TABLE_NAMES);
|
triggerUserCacheRefresh(TEST_UTIL, true, TABLE_NAMES);
|
||||||
assertEquals(60, doPuts(60, tables));
|
assertEquals(60, doPuts(60, FAMILY, QUALIFIER, tables));
|
||||||
assertEquals(60, doGets(60, tables));
|
assertEquals(60, doGets(60, tables));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,22 +172,22 @@ public class TestQuotaThrottle {
|
||||||
final String userName = User.getCurrent().getShortName();
|
final String userName = User.getCurrent().getShortName();
|
||||||
|
|
||||||
// Add 6req/min limit
|
// Add 6req/min limit
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(QuotaSettingsFactory.throttleUser(userName, TABLE_NAMES[0],
|
||||||
.throttleUser(userName, TABLE_NAMES[0], ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
|
ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
|
||||||
triggerUserCacheRefresh(false, TABLE_NAMES[0]);
|
triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
|
|
||||||
// should execute at max 6 requests on tables[0] and have no limit on tables[1]
|
// should execute at max 6 requests on tables[0] and have no limit on tables[1]
|
||||||
assertEquals(6, doPuts(100, tables[0]));
|
assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
|
||||||
assertEquals(30, doPuts(30, tables[1]));
|
assertEquals(30, doPuts(30, FAMILY, QUALIFIER, tables[1]));
|
||||||
|
|
||||||
// wait a minute and you should get other 6 requests executed
|
// wait a minute and you should get other 6 requests executed
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
assertEquals(6, doPuts(100, tables[0]));
|
assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
|
||||||
|
|
||||||
// Remove all the limits
|
// Remove all the limits
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName, TABLE_NAMES[0]));
|
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName, TABLE_NAMES[0]));
|
||||||
triggerUserCacheRefresh(true, TABLE_NAMES);
|
triggerUserCacheRefresh(TEST_UTIL, true, TABLE_NAMES);
|
||||||
assertEquals(60, doPuts(60, tables));
|
assertEquals(60, doPuts(60, FAMILY, QUALIFIER, tables));
|
||||||
assertEquals(60, doGets(60, tables));
|
assertEquals(60, doGets(60, tables));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,38 +197,38 @@ public class TestQuotaThrottle {
|
||||||
final String userName = User.getCurrent().getShortName();
|
final String userName = User.getCurrent().getShortName();
|
||||||
|
|
||||||
// Add 6req/min limit for write request on tables[0]
|
// Add 6req/min limit for write request on tables[0]
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(QuotaSettingsFactory.throttleUser(userName, TABLE_NAMES[0],
|
||||||
.throttleUser(userName, TABLE_NAMES[0], ThrottleType.WRITE_NUMBER, 6, TimeUnit.MINUTES));
|
ThrottleType.WRITE_NUMBER, 6, TimeUnit.MINUTES));
|
||||||
triggerUserCacheRefresh(false, TABLE_NAMES[0]);
|
triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
|
|
||||||
// should execute at max 6 write requests and have no limit for read request
|
// should execute at max 6 write requests and have no limit for read request
|
||||||
assertEquals(6, doPuts(100, tables[0]));
|
assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
|
||||||
assertEquals(60, doGets(60, tables[0]));
|
assertEquals(60, doGets(60, tables[0]));
|
||||||
|
|
||||||
// no limit on tables[1]
|
// no limit on tables[1]
|
||||||
assertEquals(60, doPuts(60, tables[1]));
|
assertEquals(60, doPuts(60, FAMILY, QUALIFIER, tables[1]));
|
||||||
assertEquals(60, doGets(60, tables[1]));
|
assertEquals(60, doGets(60, tables[1]));
|
||||||
|
|
||||||
// wait a minute and you should get other 6 write requests executed
|
// wait a minute and you should get other 6 write requests executed
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
|
|
||||||
// Add 6req/min limit for read request on tables[0]
|
// Add 6req/min limit for read request on tables[0]
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(QuotaSettingsFactory.throttleUser(userName, TABLE_NAMES[0],
|
||||||
.throttleUser(userName, TABLE_NAMES[0], ThrottleType.READ_NUMBER, 6, TimeUnit.MINUTES));
|
ThrottleType.READ_NUMBER, 6, TimeUnit.MINUTES));
|
||||||
triggerUserCacheRefresh(false, TABLE_NAMES[0]);
|
triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
|
|
||||||
// should execute at max 6 read requests and at max 6 write requests
|
// should execute at max 6 read requests and at max 6 write requests
|
||||||
assertEquals(6, doPuts(100, tables[0]));
|
assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
|
||||||
assertEquals(6, doGets(60, tables[0]));
|
assertEquals(6, doGets(60, tables[0]));
|
||||||
|
|
||||||
// no limit on tables[1]
|
// no limit on tables[1]
|
||||||
assertEquals(30, doPuts(30, tables[1]));
|
assertEquals(30, doPuts(30, FAMILY, QUALIFIER, tables[1]));
|
||||||
assertEquals(30, doGets(30, tables[1]));
|
assertEquals(30, doGets(30, tables[1]));
|
||||||
|
|
||||||
// Remove all the limits
|
// Remove all the limits
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName, TABLE_NAMES[0]));
|
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName, TABLE_NAMES[0]));
|
||||||
triggerUserCacheRefresh(true, TABLE_NAMES);
|
triggerUserCacheRefresh(TEST_UTIL, true, TABLE_NAMES);
|
||||||
assertEquals(60, doPuts(60, tables));
|
assertEquals(60, doPuts(60, FAMILY, QUALIFIER, tables));
|
||||||
assertEquals(60, doGets(60, tables));
|
assertEquals(60, doGets(60, tables));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,21 +239,21 @@ public class TestQuotaThrottle {
|
||||||
final String NAMESPACE = "default";
|
final String NAMESPACE = "default";
|
||||||
|
|
||||||
// Add 6req/min limit
|
// Add 6req/min limit
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(QuotaSettingsFactory.throttleUser(userName, NAMESPACE,
|
||||||
.throttleUser(userName, NAMESPACE, ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
|
ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
|
||||||
triggerUserCacheRefresh(false, TABLE_NAMES[0]);
|
triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
|
|
||||||
// should execute at max 6 requests on tables[0] and have no limit on tables[1]
|
// should execute at max 6 requests on tables[0] and have no limit on tables[1]
|
||||||
assertEquals(6, doPuts(100, tables[0]));
|
assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
|
||||||
|
|
||||||
// wait a minute and you should get other 6 requests executed
|
// wait a minute and you should get other 6 requests executed
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
assertEquals(6, doPuts(100, tables[1]));
|
assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[1]));
|
||||||
|
|
||||||
// Remove all the limits
|
// Remove all the limits
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName, NAMESPACE));
|
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName, NAMESPACE));
|
||||||
triggerUserCacheRefresh(true, TABLE_NAMES);
|
triggerUserCacheRefresh(TEST_UTIL, true, TABLE_NAMES);
|
||||||
assertEquals(60, doPuts(60, tables));
|
assertEquals(60, doPuts(60, FAMILY, QUALIFIER, tables));
|
||||||
assertEquals(60, doGets(60, tables));
|
assertEquals(60, doGets(60, tables));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,29 +264,29 @@ public class TestQuotaThrottle {
|
||||||
final String NAMESPACE = "default";
|
final String NAMESPACE = "default";
|
||||||
|
|
||||||
// Add 6req/min limit for read request
|
// Add 6req/min limit for read request
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(QuotaSettingsFactory.throttleUser(userName, NAMESPACE, ThrottleType.READ_NUMBER,
|
||||||
.throttleUser(userName, NAMESPACE, ThrottleType.READ_NUMBER, 6, TimeUnit.MINUTES));
|
6, TimeUnit.MINUTES));
|
||||||
triggerUserCacheRefresh(false, TABLE_NAMES[0]);
|
triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
|
|
||||||
// should execute at max 6 read requests and have no limit for write request
|
// should execute at max 6 read requests and have no limit for write request
|
||||||
assertEquals(6, doGets(60, tables[0]));
|
assertEquals(6, doGets(60, tables[0]));
|
||||||
assertEquals(60, doPuts(60, tables[0]));
|
assertEquals(60, doPuts(60, FAMILY, QUALIFIER, tables[0]));
|
||||||
|
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
|
|
||||||
// Add 6req/min limit for write request, too
|
// Add 6req/min limit for write request, too
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(QuotaSettingsFactory.throttleUser(userName, NAMESPACE, ThrottleType.WRITE_NUMBER,
|
||||||
.throttleUser(userName, NAMESPACE, ThrottleType.WRITE_NUMBER, 6, TimeUnit.MINUTES));
|
6, TimeUnit.MINUTES));
|
||||||
triggerUserCacheRefresh(false, TABLE_NAMES[0]);
|
triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
|
|
||||||
// should execute at max 6 read requests and at max 6 write requests
|
// should execute at max 6 read requests and at max 6 write requests
|
||||||
assertEquals(6, doGets(60, tables[0]));
|
assertEquals(6, doGets(60, tables[0]));
|
||||||
assertEquals(6, doPuts(60, tables[0]));
|
assertEquals(6, doPuts(60, FAMILY, QUALIFIER, tables[0]));
|
||||||
|
|
||||||
// Remove all the limits
|
// Remove all the limits
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName, NAMESPACE));
|
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName, NAMESPACE));
|
||||||
triggerUserCacheRefresh(true, TABLE_NAMES);
|
triggerUserCacheRefresh(TEST_UTIL, true, TABLE_NAMES);
|
||||||
assertEquals(60, doPuts(60, tables));
|
assertEquals(60, doPuts(60, FAMILY, QUALIFIER, tables));
|
||||||
assertEquals(60, doGets(60, tables));
|
assertEquals(60, doGets(60, tables));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,22 +295,22 @@ public class TestQuotaThrottle {
|
||||||
final Admin admin = TEST_UTIL.getAdmin();
|
final Admin admin = TEST_UTIL.getAdmin();
|
||||||
|
|
||||||
// Add 6req/min limit
|
// Add 6req/min limit
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0], ThrottleType.REQUEST_NUMBER,
|
||||||
.throttleTable(TABLE_NAMES[0], ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
|
6, TimeUnit.MINUTES));
|
||||||
triggerTableCacheRefresh(false, TABLE_NAMES[0]);
|
triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
|
|
||||||
// should execute at max 6 requests
|
// should execute at max 6 requests
|
||||||
assertEquals(6, doPuts(100, tables[0]));
|
assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
|
||||||
// should have no limits
|
// should have no limits
|
||||||
assertEquals(30, doPuts(30, tables[1]));
|
assertEquals(30, doPuts(30, FAMILY, QUALIFIER, tables[1]));
|
||||||
|
|
||||||
// wait a minute and you should get other 6 requests executed
|
// wait a minute and you should get other 6 requests executed
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
assertEquals(6, doPuts(100, tables[0]));
|
assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
|
||||||
|
|
||||||
// Remove all the limits
|
// Remove all the limits
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
|
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
|
||||||
triggerTableCacheRefresh(true, TABLE_NAMES[0]);
|
triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
|
||||||
assertEquals(80, doGets(80, tables[0], tables[1]));
|
assertEquals(80, doGets(80, tables[0], tables[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,35 +319,35 @@ public class TestQuotaThrottle {
|
||||||
final Admin admin = TEST_UTIL.getAdmin();
|
final Admin admin = TEST_UTIL.getAdmin();
|
||||||
|
|
||||||
// Add 6req/min limit for read request
|
// Add 6req/min limit for read request
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0], ThrottleType.READ_NUMBER, 6,
|
||||||
.throttleTable(TABLE_NAMES[0], ThrottleType.READ_NUMBER, 6, TimeUnit.MINUTES));
|
TimeUnit.MINUTES));
|
||||||
triggerTableCacheRefresh(false, TABLE_NAMES[0]);
|
triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
|
|
||||||
// should execute at max 6 read requests and have no limit for write request
|
// should execute at max 6 read requests and have no limit for write request
|
||||||
assertEquals(6, doGets(100, tables[0]));
|
assertEquals(6, doGets(100, tables[0]));
|
||||||
assertEquals(100, doPuts(100, tables[0]));
|
assertEquals(100, doPuts(100, FAMILY, QUALIFIER, tables[0]));
|
||||||
// should have no limits on tables[1]
|
// should have no limits on tables[1]
|
||||||
assertEquals(30, doPuts(30, tables[1]));
|
assertEquals(30, doPuts(30, FAMILY, QUALIFIER, tables[1]));
|
||||||
assertEquals(30, doGets(30, tables[1]));
|
assertEquals(30, doGets(30, tables[1]));
|
||||||
|
|
||||||
// wait a minute and you should get other 6 requests executed
|
// wait a minute and you should get other 6 requests executed
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
|
|
||||||
// Add 6req/min limit for write request, too
|
// Add 6req/min limit for write request, too
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0], ThrottleType.WRITE_NUMBER, 6,
|
||||||
.throttleTable(TABLE_NAMES[0], ThrottleType.WRITE_NUMBER, 6, TimeUnit.MINUTES));
|
TimeUnit.MINUTES));
|
||||||
triggerTableCacheRefresh(false, TABLE_NAMES[0]);
|
triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
|
|
||||||
// should execute at max 6 read requests and at max 6 write requests
|
// should execute at max 6 read requests and at max 6 write requests
|
||||||
assertEquals(6, doGets(100, tables[0]));
|
assertEquals(6, doGets(100, tables[0]));
|
||||||
assertEquals(6, doPuts(100, tables[0]));
|
assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
|
||||||
// should have no limits on tables[1]
|
// should have no limits on tables[1]
|
||||||
assertEquals(30, doPuts(30, tables[1]));
|
assertEquals(30, doPuts(30, FAMILY, QUALIFIER, tables[1]));
|
||||||
assertEquals(30, doGets(30, tables[1]));
|
assertEquals(30, doGets(30, tables[1]));
|
||||||
|
|
||||||
// Remove all the limits
|
// Remove all the limits
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
|
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
|
||||||
triggerTableCacheRefresh(true, TABLE_NAMES[0]);
|
triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
|
||||||
assertEquals(80, doGets(80, tables[0], tables[1]));
|
assertEquals(80, doGets(80, tables[0], tables[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,20 +357,20 @@ public class TestQuotaThrottle {
|
||||||
final String NAMESPACE = "default";
|
final String NAMESPACE = "default";
|
||||||
|
|
||||||
// Add 6req/min limit
|
// Add 6req/min limit
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(QuotaSettingsFactory.throttleNamespace(NAMESPACE, ThrottleType.REQUEST_NUMBER, 6,
|
||||||
.throttleNamespace(NAMESPACE, ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
|
TimeUnit.MINUTES));
|
||||||
triggerNamespaceCacheRefresh(false, TABLE_NAMES[0]);
|
triggerNamespaceCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
|
|
||||||
// should execute at max 6 requests
|
// should execute at max 6 requests
|
||||||
assertEquals(6, doPuts(100, tables[0]));
|
assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
|
||||||
|
|
||||||
// wait a minute and you should get other 6 requests executed
|
// wait a minute and you should get other 6 requests executed
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
assertEquals(6, doPuts(100, tables[1]));
|
assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[1]));
|
||||||
|
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleNamespace(NAMESPACE));
|
admin.setQuota(QuotaSettingsFactory.unthrottleNamespace(NAMESPACE));
|
||||||
triggerNamespaceCacheRefresh(true, TABLE_NAMES[0]);
|
triggerNamespaceCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
|
||||||
assertEquals(40, doPuts(40, tables[0]));
|
assertEquals(40, doPuts(40, FAMILY, QUALIFIER, tables[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -388,29 +379,29 @@ public class TestQuotaThrottle {
|
||||||
final String NAMESPACE = "default";
|
final String NAMESPACE = "default";
|
||||||
|
|
||||||
// Add 6req/min limit for write request
|
// Add 6req/min limit for write request
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(QuotaSettingsFactory.throttleNamespace(NAMESPACE, ThrottleType.WRITE_NUMBER, 6,
|
||||||
.throttleNamespace(NAMESPACE, ThrottleType.WRITE_NUMBER, 6, TimeUnit.MINUTES));
|
TimeUnit.MINUTES));
|
||||||
triggerNamespaceCacheRefresh(false, TABLE_NAMES[0]);
|
triggerNamespaceCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
|
|
||||||
// should execute at max 6 write requests and no limit for read request
|
// should execute at max 6 write requests and no limit for read request
|
||||||
assertEquals(6, doPuts(100, tables[0]));
|
assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
|
||||||
assertEquals(100, doGets(100, tables[0]));
|
assertEquals(100, doGets(100, tables[0]));
|
||||||
|
|
||||||
// wait a minute and you should get other 6 requests executed
|
// wait a minute and you should get other 6 requests executed
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
|
|
||||||
// Add 6req/min limit for read request, too
|
// Add 6req/min limit for read request, too
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(QuotaSettingsFactory.throttleNamespace(NAMESPACE, ThrottleType.READ_NUMBER, 6,
|
||||||
.throttleNamespace(NAMESPACE, ThrottleType.READ_NUMBER, 6, TimeUnit.MINUTES));
|
TimeUnit.MINUTES));
|
||||||
triggerNamespaceCacheRefresh(false, TABLE_NAMES[0]);
|
triggerNamespaceCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
|
|
||||||
// should execute at max 6 write requests and at max 6 read requests
|
// should execute at max 6 write requests and at max 6 read requests
|
||||||
assertEquals(6, doPuts(100, tables[0]));
|
assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
|
||||||
assertEquals(6, doGets(100, tables[0]));
|
assertEquals(6, doGets(100, tables[0]));
|
||||||
|
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleNamespace(NAMESPACE));
|
admin.setQuota(QuotaSettingsFactory.unthrottleNamespace(NAMESPACE));
|
||||||
triggerNamespaceCacheRefresh(true, TABLE_NAMES[0]);
|
triggerNamespaceCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
|
||||||
assertEquals(40, doPuts(40, tables[0]));
|
assertEquals(40, doPuts(40, FAMILY, QUALIFIER, tables[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -419,21 +410,21 @@ public class TestQuotaThrottle {
|
||||||
final String userName = User.getCurrent().getShortName();
|
final String userName = User.getCurrent().getShortName();
|
||||||
|
|
||||||
// Add 6req/min limit for the user on tables[0]
|
// Add 6req/min limit for the user on tables[0]
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(QuotaSettingsFactory.throttleUser(userName, TABLE_NAMES[0],
|
||||||
.throttleUser(userName, TABLE_NAMES[0], ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
|
ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
|
||||||
triggerUserCacheRefresh(false, TABLE_NAMES[0]);
|
triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
// Add 12req/min limit for the user
|
// Add 12req/min limit for the user
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(QuotaSettingsFactory.throttleUser(userName, ThrottleType.REQUEST_NUMBER, 12,
|
||||||
.throttleUser(userName, ThrottleType.REQUEST_NUMBER, 12, TimeUnit.MINUTES));
|
TimeUnit.MINUTES));
|
||||||
triggerUserCacheRefresh(false, TABLE_NAMES[1], TABLE_NAMES[2]);
|
triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES[1], TABLE_NAMES[2]);
|
||||||
// Add 8req/min limit for the tables[1]
|
// Add 8req/min limit for the tables[1]
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[1], ThrottleType.REQUEST_NUMBER,
|
||||||
.throttleTable(TABLE_NAMES[1], ThrottleType.REQUEST_NUMBER, 8, TimeUnit.MINUTES));
|
8, TimeUnit.MINUTES));
|
||||||
triggerTableCacheRefresh(false, TABLE_NAMES[1]);
|
triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[1]);
|
||||||
// Add a lower table level throttle on tables[0]
|
// Add a lower table level throttle on tables[0]
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0], ThrottleType.REQUEST_NUMBER,
|
||||||
.throttleTable(TABLE_NAMES[0], ThrottleType.REQUEST_NUMBER, 3, TimeUnit.MINUTES));
|
3, TimeUnit.MINUTES));
|
||||||
triggerTableCacheRefresh(false, TABLE_NAMES[0]);
|
triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
|
|
||||||
// should execute at max 12 requests
|
// should execute at max 12 requests
|
||||||
assertEquals(12, doGets(100, tables[2]));
|
assertEquals(12, doGets(100, tables[2]));
|
||||||
|
@ -444,20 +435,20 @@ public class TestQuotaThrottle {
|
||||||
|
|
||||||
// should execute at max 3 requests
|
// should execute at max 3 requests
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
assertEquals(3, doPuts(100, tables[0]));
|
assertEquals(3, doPuts(100, FAMILY, QUALIFIER, tables[0]));
|
||||||
|
|
||||||
// Remove all the throttling rules
|
// Remove all the throttling rules
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName, TABLE_NAMES[0]));
|
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName, TABLE_NAMES[0]));
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName));
|
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName));
|
||||||
triggerUserCacheRefresh(true, TABLE_NAMES[0], TABLE_NAMES[1]);
|
triggerUserCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0], TABLE_NAMES[1]);
|
||||||
|
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[1]));
|
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[1]));
|
||||||
triggerTableCacheRefresh(true, TABLE_NAMES[1]);
|
triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAMES[1]);
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
assertEquals(40, doGets(40, tables[1]));
|
assertEquals(40, doGets(40, tables[1]));
|
||||||
|
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
|
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
|
||||||
triggerTableCacheRefresh(true, TABLE_NAMES[0]);
|
triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
assertEquals(40, doGets(40, tables[0]));
|
assertEquals(40, doGets(40, tables[0]));
|
||||||
}
|
}
|
||||||
|
@ -469,24 +460,24 @@ public class TestQuotaThrottle {
|
||||||
final String NAMESPACE = "default";
|
final String NAMESPACE = "default";
|
||||||
|
|
||||||
// Add 6req/min limit for tables[0]
|
// Add 6req/min limit for tables[0]
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0], ThrottleType.REQUEST_NUMBER,
|
||||||
.throttleTable(TABLE_NAMES[0], ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
|
6, TimeUnit.MINUTES));
|
||||||
triggerTableCacheRefresh(false, TABLE_NAMES[0]);
|
triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
// Add 13req/min limit for the user
|
// Add 13req/min limit for the user
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(QuotaSettingsFactory.throttleNamespace(NAMESPACE, ThrottleType.REQUEST_NUMBER,
|
||||||
.throttleNamespace(NAMESPACE, ThrottleType.REQUEST_NUMBER, 13, TimeUnit.MINUTES));
|
13, TimeUnit.MINUTES));
|
||||||
triggerNamespaceCacheRefresh(false, TABLE_NAMES[1]);
|
triggerNamespaceCacheRefresh(TEST_UTIL, false, TABLE_NAMES[1]);
|
||||||
|
|
||||||
// should execute at max 6 requests on table[0] and (13 - 6) on table[1]
|
// should execute at max 6 requests on table[0] and (13 - 6) on table[1]
|
||||||
assertEquals(6, doPuts(100, tables[0]));
|
assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
|
||||||
assertEquals(7, doGets(100, tables[1]));
|
assertEquals(7, doGets(100, tables[1]));
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
|
|
||||||
// Set the global bypass for the user
|
// Set the global bypass for the user
|
||||||
admin.setQuota(QuotaSettingsFactory.bypassGlobals(userName, true));
|
admin.setQuota(QuotaSettingsFactory.bypassGlobals(userName, true));
|
||||||
admin.setQuota(QuotaSettingsFactory
|
admin.setQuota(QuotaSettingsFactory.throttleUser(userName, TABLE_NAMES[2],
|
||||||
.throttleUser(userName, TABLE_NAMES[2], ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
|
ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
|
||||||
triggerUserCacheRefresh(false, TABLE_NAMES[2]);
|
triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES[2]);
|
||||||
assertEquals(30, doGets(30, tables[0]));
|
assertEquals(30, doGets(30, tables[0]));
|
||||||
assertEquals(30, doGets(30, tables[1]));
|
assertEquals(30, doGets(30, tables[1]));
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
|
@ -495,16 +486,16 @@ public class TestQuotaThrottle {
|
||||||
// should execute at max 6 requests on table[0] and (13 - 6) on table[1]
|
// should execute at max 6 requests on table[0] and (13 - 6) on table[1]
|
||||||
admin.setQuota(QuotaSettingsFactory.bypassGlobals(userName, false));
|
admin.setQuota(QuotaSettingsFactory.bypassGlobals(userName, false));
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName, TABLE_NAMES[2]));
|
admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName, TABLE_NAMES[2]));
|
||||||
triggerUserCacheRefresh(true, TABLE_NAMES[2]);
|
triggerUserCacheRefresh(TEST_UTIL, true, TABLE_NAMES[2]);
|
||||||
assertEquals(6, doPuts(100, tables[0]));
|
assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
|
||||||
assertEquals(7, doGets(100, tables[1]));
|
assertEquals(7, doGets(100, tables[1]));
|
||||||
|
|
||||||
// unset throttle
|
// unset throttle
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
|
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleNamespace(NAMESPACE));
|
admin.setQuota(QuotaSettingsFactory.unthrottleNamespace(NAMESPACE));
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
triggerTableCacheRefresh(true, TABLE_NAMES[0]);
|
triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
|
||||||
triggerNamespaceCacheRefresh(true, TABLE_NAMES[1]);
|
triggerNamespaceCacheRefresh(TEST_UTIL, true, TABLE_NAMES[1]);
|
||||||
assertEquals(30, doGets(30, tables[0]));
|
assertEquals(30, doGets(30, tables[0]));
|
||||||
assertEquals(30, doGets(30, tables[1]));
|
assertEquals(30, doGets(30, tables[1]));
|
||||||
}
|
}
|
||||||
|
@ -516,18 +507,18 @@ public class TestQuotaThrottle {
|
||||||
// Add 6CU/min limit
|
// Add 6CU/min limit
|
||||||
admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0],
|
admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0],
|
||||||
ThrottleType.WRITE_CAPACITY_UNIT, 6, TimeUnit.MINUTES));
|
ThrottleType.WRITE_CAPACITY_UNIT, 6, TimeUnit.MINUTES));
|
||||||
triggerTableCacheRefresh(false, TABLE_NAMES[0]);
|
triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
|
|
||||||
// should execute at max 6 capacity units because each put size is 1 capacity unit
|
// should execute at max 6 capacity units because each put size is 1 capacity unit
|
||||||
assertEquals(6, doPuts(20, 10, tables[0]));
|
assertEquals(6, doPuts(20, 10, FAMILY, QUALIFIER, tables[0]));
|
||||||
|
|
||||||
// wait a minute and you should execute at max 3 capacity units because each put size is 2
|
// wait a minute and you should execute at max 3 capacity units because each put size is 2
|
||||||
// capacity unit
|
// capacity unit
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
assertEquals(3, doPuts(20, 1025, tables[0]));
|
assertEquals(3, doPuts(20, 1025, FAMILY, QUALIFIER, tables[0]));
|
||||||
|
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
|
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
|
||||||
triggerTableCacheRefresh(true, TABLE_NAMES[0]);
|
triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -537,20 +528,20 @@ public class TestQuotaThrottle {
|
||||||
// Add 6CU/min limit
|
// Add 6CU/min limit
|
||||||
admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0],
|
admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0],
|
||||||
ThrottleType.READ_CAPACITY_UNIT, 6, TimeUnit.MINUTES));
|
ThrottleType.READ_CAPACITY_UNIT, 6, TimeUnit.MINUTES));
|
||||||
triggerTableCacheRefresh(false, TABLE_NAMES[0]);
|
triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
|
|
||||||
assertEquals(20, doPuts(20, 10, tables[0]));
|
assertEquals(20, doPuts(20, 10, FAMILY, QUALIFIER, tables[0]));
|
||||||
// should execute at max 6 capacity units because each get size is 1 capacity unit
|
// should execute at max 6 capacity units because each get size is 1 capacity unit
|
||||||
assertEquals(6, doGets(20, tables[0]));
|
assertEquals(6, doGets(20, tables[0]));
|
||||||
|
|
||||||
assertEquals(20, doPuts(20, 2015, tables[0]));
|
assertEquals(20, doPuts(20, 2015, FAMILY, QUALIFIER, tables[0]));
|
||||||
// wait a minute and you should execute at max 3 capacity units because each get size is 2
|
// wait a minute and you should execute at max 3 capacity units because each get size is 2
|
||||||
// capacity unit on tables[0]
|
// capacity unit on tables[0]
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
assertEquals(3, doGets(20, tables[0]));
|
assertEquals(3, doGets(20, tables[0]));
|
||||||
|
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
|
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
|
||||||
triggerTableCacheRefresh(true, TABLE_NAMES[0]);
|
triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -558,16 +549,16 @@ public class TestQuotaThrottle {
|
||||||
final Admin admin = TEST_UTIL.getAdmin();
|
final Admin admin = TEST_UTIL.getAdmin();
|
||||||
|
|
||||||
// Add throttle quota
|
// Add throttle quota
|
||||||
admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0],
|
admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0], ThrottleType.REQUEST_NUMBER,
|
||||||
ThrottleType.REQUEST_NUMBER, 100, TimeUnit.MINUTES));
|
100, TimeUnit.MINUTES));
|
||||||
triggerTableCacheRefresh(false, TABLE_NAMES[0]);
|
triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
|
|
||||||
Table table = TEST_UTIL.getConnection().getTable(TABLE_NAMES[0]);
|
Table table = TEST_UTIL.getConnection().getTable(TABLE_NAMES[0]);
|
||||||
// An exists call when having throttle quota
|
// An exists call when having throttle quota
|
||||||
table.exists(new Get(Bytes.toBytes("abc")));
|
table.exists(new Get(Bytes.toBytes("abc")));
|
||||||
|
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
|
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
|
||||||
triggerTableCacheRefresh(true, TABLE_NAMES[0]);
|
triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -579,22 +570,27 @@ public class TestQuotaThrottle {
|
||||||
// requests are throttled by table quota
|
// requests are throttled by table quota
|
||||||
admin.setQuota(QuotaSettingsFactory.throttleRegionServer(
|
admin.setQuota(QuotaSettingsFactory.throttleRegionServer(
|
||||||
QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY, ThrottleType.WRITE_NUMBER, 7, TimeUnit.MINUTES));
|
QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY, ThrottleType.WRITE_NUMBER, 7, TimeUnit.MINUTES));
|
||||||
triggerTableCacheRefresh(false, TABLE_NAMES[0]);
|
triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
triggerRegionServerCacheRefresh(false);
|
triggerRegionServerCacheRefresh(TEST_UTIL, false);
|
||||||
assertEquals(5, doPuts(10, tables[0]));
|
assertEquals(5, doPuts(10, FAMILY, QUALIFIER, tables[0]));
|
||||||
|
triggerRegionServerCacheRefresh(TEST_UTIL, false);
|
||||||
|
assertEquals(5, doPuts(10, FAMILY, QUALIFIER, tables[0]));
|
||||||
|
|
||||||
// requests are throttled by region server quota
|
// requests are throttled by region server quota
|
||||||
admin.setQuota(QuotaSettingsFactory.throttleRegionServer(
|
admin.setQuota(QuotaSettingsFactory.throttleRegionServer(
|
||||||
QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY, ThrottleType.WRITE_NUMBER, 4, TimeUnit.MINUTES));
|
QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY, ThrottleType.WRITE_NUMBER, 4, TimeUnit.MINUTES));
|
||||||
triggerRegionServerCacheRefresh(false);
|
triggerRegionServerCacheRefresh(TEST_UTIL, false);
|
||||||
assertEquals(4, doPuts(10, tables[0]));
|
assertEquals(4, doPuts(10, FAMILY, QUALIFIER, tables[0]));
|
||||||
|
triggerRegionServerCacheRefresh(TEST_UTIL, false);
|
||||||
|
assertEquals(4, doPuts(10, FAMILY, QUALIFIER, tables[0]));
|
||||||
|
|
||||||
// unthrottle
|
// unthrottle
|
||||||
admin.setQuota(
|
admin.setQuota(
|
||||||
QuotaSettingsFactory.unthrottleRegionServer(QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY));
|
QuotaSettingsFactory.unthrottleRegionServer(QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY));
|
||||||
|
triggerRegionServerCacheRefresh(TEST_UTIL, true);
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
|
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
|
||||||
triggerTableCacheRefresh(true, TABLE_NAMES[0]);
|
triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
|
||||||
triggerRegionServerCacheRefresh(true);
|
triggerRegionServerCacheRefresh(TEST_UTIL, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -602,195 +598,57 @@ public class TestQuotaThrottle {
|
||||||
final Admin admin = TEST_UTIL.getAdmin();
|
final Admin admin = TEST_UTIL.getAdmin();
|
||||||
admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0], ThrottleType.WRITE_NUMBER, 5,
|
admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0], ThrottleType.WRITE_NUMBER, 5,
|
||||||
TimeUnit.MINUTES));
|
TimeUnit.MINUTES));
|
||||||
triggerTableCacheRefresh(false, TABLE_NAMES[0]);
|
triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
|
||||||
admin.setQuota(QuotaSettingsFactory.throttleRegionServer(
|
admin.setQuota(QuotaSettingsFactory.throttleRegionServer(
|
||||||
QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY, ThrottleType.WRITE_NUMBER, 20, TimeUnit.SECONDS));
|
QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY, ThrottleType.WRITE_NUMBER, 20, TimeUnit.SECONDS));
|
||||||
admin.setQuota(QuotaSettingsFactory.throttleRegionServer(
|
admin.setQuota(QuotaSettingsFactory.throttleRegionServer(
|
||||||
QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY, ThrottleType.READ_NUMBER, 10, TimeUnit.SECONDS));
|
QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY, ThrottleType.READ_NUMBER, 10, TimeUnit.SECONDS));
|
||||||
triggerRegionServerCacheRefresh(false);
|
triggerRegionServerCacheRefresh(TEST_UTIL, false);
|
||||||
|
|
||||||
// enable exceed throttle quota
|
// enable exceed throttle quota
|
||||||
admin.exceedThrottleQuotaSwitch(true);
|
admin.exceedThrottleQuotaSwitch(true);
|
||||||
// exceed table limit and allowed by region server limit
|
// exceed table limit and allowed by region server limit
|
||||||
triggerExceedThrottleQuotaCacheRefresh(true);
|
triggerExceedThrottleQuotaCacheRefresh(TEST_UTIL, true);
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
assertEquals(10, doPuts(10, tables[0]));
|
assertEquals(10, doPuts(10, FAMILY, QUALIFIER, tables[0]));
|
||||||
// exceed table limit and throttled by region server limit
|
// exceed table limit and throttled by region server limit
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
assertEquals(20, doPuts(25, tables[0]));
|
assertEquals(20, doPuts(25, FAMILY, QUALIFIER, tables[0]));
|
||||||
|
|
||||||
// set region server limiter is lower than table limiter
|
// set region server limiter is lower than table limiter
|
||||||
admin.setQuota(QuotaSettingsFactory.throttleRegionServer(
|
admin.setQuota(QuotaSettingsFactory.throttleRegionServer(
|
||||||
QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY, ThrottleType.WRITE_NUMBER, 2, TimeUnit.SECONDS));
|
QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY, ThrottleType.WRITE_NUMBER, 2, TimeUnit.SECONDS));
|
||||||
triggerRegionServerCacheRefresh(false);
|
triggerRegionServerCacheRefresh(TEST_UTIL, false);
|
||||||
// throttled by region server limiter
|
// throttled by region server limiter
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
assertEquals(2, doPuts(10, tables[0]));
|
assertEquals(2, doPuts(10, FAMILY, QUALIFIER, tables[0]));
|
||||||
admin.setQuota(QuotaSettingsFactory.throttleRegionServer(
|
admin.setQuota(QuotaSettingsFactory.throttleRegionServer(
|
||||||
QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY, ThrottleType.WRITE_NUMBER, 20, TimeUnit.SECONDS));
|
QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY, ThrottleType.WRITE_NUMBER, 20, TimeUnit.SECONDS));
|
||||||
triggerRegionServerCacheRefresh(false);
|
triggerRegionServerCacheRefresh(TEST_UTIL, false);
|
||||||
|
|
||||||
// disable exceed throttle quota
|
// disable exceed throttle quota
|
||||||
admin.exceedThrottleQuotaSwitch(false);
|
admin.exceedThrottleQuotaSwitch(false);
|
||||||
triggerExceedThrottleQuotaCacheRefresh(false);
|
triggerExceedThrottleQuotaCacheRefresh(TEST_UTIL, false);
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
// throttled by table limit
|
// throttled by table limit
|
||||||
assertEquals(5, doPuts(10, tables[0]));
|
assertEquals(5, doPuts(10, FAMILY, QUALIFIER, tables[0]));
|
||||||
|
|
||||||
// enable exceed throttle quota and unthrottle region server
|
// enable exceed throttle quota and unthrottle region server
|
||||||
admin.exceedThrottleQuotaSwitch(true);
|
admin.exceedThrottleQuotaSwitch(true);
|
||||||
triggerExceedThrottleQuotaCacheRefresh(true);
|
triggerExceedThrottleQuotaCacheRefresh(TEST_UTIL, true);
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
admin.setQuota(
|
admin.setQuota(
|
||||||
QuotaSettingsFactory.unthrottleRegionServer(QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY));
|
QuotaSettingsFactory.unthrottleRegionServer(QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY));
|
||||||
triggerRegionServerCacheRefresh(true);
|
triggerRegionServerCacheRefresh(TEST_UTIL, true);
|
||||||
waitMinuteQuota();
|
waitMinuteQuota();
|
||||||
// throttled by table limit
|
// throttled by table limit
|
||||||
assertEquals(5, doPuts(10, tables[0]));
|
assertEquals(5, doPuts(10, FAMILY, QUALIFIER, tables[0]));
|
||||||
|
|
||||||
// disable exceed throttle quota
|
// disable exceed throttle quota
|
||||||
admin.exceedThrottleQuotaSwitch(false);
|
admin.exceedThrottleQuotaSwitch(false);
|
||||||
triggerExceedThrottleQuotaCacheRefresh(false);
|
triggerExceedThrottleQuotaCacheRefresh(TEST_UTIL, false);
|
||||||
// unthrottle table
|
// unthrottle table
|
||||||
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
|
admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
|
||||||
triggerTableCacheRefresh(true, TABLE_NAMES[0]);
|
triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
|
||||||
}
|
|
||||||
|
|
||||||
private int doPuts(int maxOps, final Table... tables) throws Exception {
|
|
||||||
return doPuts(maxOps, -1, tables);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int doPuts(int maxOps, int valueSize, final Table... tables) throws Exception {
|
|
||||||
int count = 0;
|
|
||||||
try {
|
|
||||||
while (count < maxOps) {
|
|
||||||
Put put = new Put(Bytes.toBytes("row-" + count));
|
|
||||||
byte[] value;
|
|
||||||
if (valueSize < 0) {
|
|
||||||
value = Bytes.toBytes("data-" + count);
|
|
||||||
} else {
|
|
||||||
value = generateValue(valueSize);
|
|
||||||
}
|
|
||||||
put.addColumn(FAMILY, QUALIFIER, value);
|
|
||||||
for (final Table table : tables) {
|
|
||||||
table.put(put);
|
|
||||||
}
|
|
||||||
count += tables.length;
|
|
||||||
}
|
|
||||||
} catch (RpcThrottlingException e) {
|
|
||||||
LOG.error("put failed after nRetries=" + count, e);
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] generateValue(int valueSize) {
|
|
||||||
byte[] bytes = new byte[valueSize];
|
|
||||||
for (int i = 0; i < valueSize; i++) {
|
|
||||||
bytes[i] = 'a';
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
private long doGets(int maxOps, final Table... tables) throws Exception {
|
|
||||||
int count = 0;
|
|
||||||
try {
|
|
||||||
while (count < maxOps) {
|
|
||||||
Get get = new Get(Bytes.toBytes("row-" + count));
|
|
||||||
for (final Table table: tables) {
|
|
||||||
table.get(get);
|
|
||||||
}
|
|
||||||
count += tables.length;
|
|
||||||
}
|
|
||||||
} catch (RpcThrottlingException e) {
|
|
||||||
LOG.error("get failed after nRetries=" + count, e);
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void triggerUserCacheRefresh(boolean bypass, TableName... tables) throws Exception {
|
|
||||||
triggerCacheRefresh(bypass, true, false, false, false, false, tables);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void triggerTableCacheRefresh(boolean bypass, TableName... tables) throws Exception {
|
|
||||||
triggerCacheRefresh(bypass, false, true, false, false, false, tables);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void triggerNamespaceCacheRefresh(boolean bypass, TableName... tables) throws Exception {
|
|
||||||
triggerCacheRefresh(bypass, false, false, true, false, false, tables);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void triggerRegionServerCacheRefresh(boolean bypass) throws Exception {
|
|
||||||
triggerCacheRefresh(bypass, false, false, false, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void triggerExceedThrottleQuotaCacheRefresh(boolean exceedEnabled) throws Exception {
|
|
||||||
triggerCacheRefresh(exceedEnabled, false, false, false, false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void triggerCacheRefresh(boolean bypass, boolean userLimiter, boolean tableLimiter,
|
|
||||||
boolean nsLimiter, boolean rsLimiter, boolean exceedThrottleQuota, final TableName... tables)
|
|
||||||
throws Exception {
|
|
||||||
envEdge.incValue(2 * REFRESH_TIME);
|
|
||||||
for (RegionServerThread rst : TEST_UTIL.getMiniHBaseCluster().getRegionServerThreads()) {
|
|
||||||
RegionServerRpcQuotaManager quotaManager =
|
|
||||||
rst.getRegionServer().getRegionServerRpcQuotaManager();
|
|
||||||
QuotaCache quotaCache = quotaManager.getQuotaCache();
|
|
||||||
|
|
||||||
quotaCache.triggerCacheRefresh();
|
|
||||||
// sleep for cache update
|
|
||||||
Thread.sleep(250);
|
|
||||||
|
|
||||||
for (TableName table : tables) {
|
|
||||||
quotaCache.getTableLimiter(table);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isUpdated = false;
|
|
||||||
while (!isUpdated) {
|
|
||||||
quotaCache.triggerCacheRefresh();
|
|
||||||
isUpdated = true;
|
|
||||||
for (TableName table : tables) {
|
|
||||||
boolean isBypass = true;
|
|
||||||
if (userLimiter) {
|
|
||||||
isBypass &= quotaCache.getUserLimiter(User.getCurrent().getUGI(), table).isBypass();
|
|
||||||
}
|
|
||||||
if (tableLimiter) {
|
|
||||||
isBypass &= quotaCache.getTableLimiter(table).isBypass();
|
|
||||||
}
|
|
||||||
if (nsLimiter) {
|
|
||||||
isBypass &= quotaCache.getNamespaceLimiter(table.getNamespaceAsString()).isBypass();
|
|
||||||
}
|
|
||||||
if (isBypass != bypass) {
|
|
||||||
envEdge.incValue(100);
|
|
||||||
isUpdated = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rsLimiter) {
|
|
||||||
boolean rsIsBypass = quotaCache
|
|
||||||
.getRegionServerQuotaLimiter(QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY).isBypass();
|
|
||||||
if (rsIsBypass != bypass) {
|
|
||||||
envEdge.incValue(100);
|
|
||||||
isUpdated = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (exceedThrottleQuota) {
|
|
||||||
if (quotaCache.isExceedThrottleQuotaEnabled() != bypass) {
|
|
||||||
envEdge.incValue(100);
|
|
||||||
isUpdated = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG.debug("QuotaCache");
|
|
||||||
LOG.debug(Objects.toString(quotaCache.getNamespaceQuotaCache()));
|
|
||||||
LOG.debug(Objects.toString(quotaCache.getTableQuotaCache()));
|
|
||||||
LOG.debug(Objects.toString(quotaCache.getUserQuotaCache()));
|
|
||||||
LOG.debug(Objects.toString(quotaCache.getRegionServerQuotaCache()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void waitMinuteQuota() {
|
|
||||||
envEdge.incValue(70000);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,207 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.hadoop.hbase.quotas;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
||||||
|
import org.apache.hadoop.hbase.TableName;
|
||||||
|
import org.apache.hadoop.hbase.client.Get;
|
||||||
|
import org.apache.hadoop.hbase.client.Put;
|
||||||
|
import org.apache.hadoop.hbase.client.Table;
|
||||||
|
import org.apache.hadoop.hbase.security.User;
|
||||||
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
|
import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
|
||||||
|
import org.apache.hadoop.hbase.util.EnvironmentEdgeManagerTestHelper;
|
||||||
|
import org.apache.hadoop.hbase.util.JVMClusterUtil.RegionServerThread;
|
||||||
|
import org.apache.hadoop.hbase.util.ManualEnvironmentEdge;
|
||||||
|
import org.apache.yetus.audience.InterfaceAudience;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@InterfaceAudience.Private
|
||||||
|
public final class ThrottleQuotaTestUtil {
|
||||||
|
|
||||||
|
private final static Logger LOG = LoggerFactory.getLogger(ThrottleQuotaTestUtil.class);
|
||||||
|
private static ManualEnvironmentEdge envEdge = new ManualEnvironmentEdge();
|
||||||
|
private final static int REFRESH_TIME = 30 * 60000;
|
||||||
|
static {
|
||||||
|
envEdge.setValue(EnvironmentEdgeManager.currentTime());
|
||||||
|
EnvironmentEdgeManagerTestHelper.injectEdge(envEdge);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ThrottleQuotaTestUtil() {
|
||||||
|
// Hide utility class constructor
|
||||||
|
LOG.debug("Call constructor of ThrottleQuotaTestUtil");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int doPuts(int maxOps, byte[] family, byte[] qualifier, final Table... tables) {
|
||||||
|
return doPuts(maxOps, -1, family, qualifier, tables);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int doPuts(int maxOps, int valueSize, byte[] family, byte[] qualifier,
|
||||||
|
final Table... tables) {
|
||||||
|
int count = 0;
|
||||||
|
try {
|
||||||
|
while (count < maxOps) {
|
||||||
|
Put put = new Put(Bytes.toBytes("row-" + count));
|
||||||
|
byte[] value;
|
||||||
|
if (valueSize < 0) {
|
||||||
|
value = Bytes.toBytes("data-" + count);
|
||||||
|
} else {
|
||||||
|
value = generateValue(valueSize);
|
||||||
|
}
|
||||||
|
put.addColumn(family, qualifier, value);
|
||||||
|
for (final Table table : tables) {
|
||||||
|
table.put(put);
|
||||||
|
}
|
||||||
|
count += tables.length;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.error("put failed after nRetries=" + count, e);
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] generateValue(int valueSize) {
|
||||||
|
byte[] bytes = new byte[valueSize];
|
||||||
|
for (int i = 0; i < valueSize; i++) {
|
||||||
|
bytes[i] = 'a';
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long doGets(int maxOps, final Table... tables) {
|
||||||
|
int count = 0;
|
||||||
|
try {
|
||||||
|
while (count < maxOps) {
|
||||||
|
Get get = new Get(Bytes.toBytes("row-" + count));
|
||||||
|
for (final Table table : tables) {
|
||||||
|
table.get(get);
|
||||||
|
}
|
||||||
|
count += tables.length;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.error("get failed after nRetries=" + count, e);
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void triggerUserCacheRefresh(HBaseTestingUtility testUtil, boolean bypass,
|
||||||
|
TableName... tables) throws Exception {
|
||||||
|
triggerCacheRefresh(testUtil, bypass, true, false, false, false, false, tables);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void triggerTableCacheRefresh(HBaseTestingUtility testUtil, boolean bypass,
|
||||||
|
TableName... tables) throws Exception {
|
||||||
|
triggerCacheRefresh(testUtil, bypass, false, true, false, false, false, tables);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void triggerNamespaceCacheRefresh(HBaseTestingUtility testUtil, boolean bypass,
|
||||||
|
TableName... tables) throws Exception {
|
||||||
|
triggerCacheRefresh(testUtil, bypass, false, false, true, false, false, tables);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void triggerRegionServerCacheRefresh(HBaseTestingUtility testUtil, boolean bypass)
|
||||||
|
throws Exception {
|
||||||
|
triggerCacheRefresh(testUtil, bypass, false, false, false, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void triggerExceedThrottleQuotaCacheRefresh(HBaseTestingUtility testUtil,
|
||||||
|
boolean exceedEnabled) throws Exception {
|
||||||
|
triggerCacheRefresh(testUtil, exceedEnabled, false, false, false, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void triggerCacheRefresh(HBaseTestingUtility testUtil, boolean bypass,
|
||||||
|
boolean userLimiter, boolean tableLimiter, boolean nsLimiter, boolean rsLimiter,
|
||||||
|
boolean exceedThrottleQuota, final TableName... tables) throws Exception {
|
||||||
|
envEdge.incValue(2 * REFRESH_TIME);
|
||||||
|
for (RegionServerThread rst : testUtil.getMiniHBaseCluster().getRegionServerThreads()) {
|
||||||
|
RegionServerRpcQuotaManager quotaManager =
|
||||||
|
rst.getRegionServer().getRegionServerRpcQuotaManager();
|
||||||
|
QuotaCache quotaCache = quotaManager.getQuotaCache();
|
||||||
|
|
||||||
|
quotaCache.triggerCacheRefresh();
|
||||||
|
// sleep for cache update
|
||||||
|
Thread.sleep(250);
|
||||||
|
|
||||||
|
for (TableName table : tables) {
|
||||||
|
quotaCache.getTableLimiter(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isUpdated = false;
|
||||||
|
while (!isUpdated) {
|
||||||
|
quotaCache.triggerCacheRefresh();
|
||||||
|
isUpdated = true;
|
||||||
|
for (TableName table : tables) {
|
||||||
|
boolean isBypass = true;
|
||||||
|
if (userLimiter) {
|
||||||
|
isBypass = quotaCache.getUserLimiter(User.getCurrent().getUGI(), table).isBypass();
|
||||||
|
}
|
||||||
|
if (tableLimiter) {
|
||||||
|
isBypass &= quotaCache.getTableLimiter(table).isBypass();
|
||||||
|
}
|
||||||
|
if (nsLimiter) {
|
||||||
|
isBypass &= quotaCache.getNamespaceLimiter(table.getNamespaceAsString()).isBypass();
|
||||||
|
}
|
||||||
|
if (isBypass != bypass) {
|
||||||
|
envEdge.incValue(100);
|
||||||
|
isUpdated = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rsLimiter) {
|
||||||
|
boolean rsIsBypass = quotaCache
|
||||||
|
.getRegionServerQuotaLimiter(QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY).isBypass();
|
||||||
|
if (rsIsBypass != bypass) {
|
||||||
|
envEdge.incValue(100);
|
||||||
|
isUpdated = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (exceedThrottleQuota) {
|
||||||
|
if (quotaCache.isExceedThrottleQuotaEnabled() != bypass) {
|
||||||
|
envEdge.incValue(100);
|
||||||
|
isUpdated = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG.debug("QuotaCache");
|
||||||
|
LOG.debug(Objects.toString(quotaCache.getNamespaceQuotaCache()));
|
||||||
|
LOG.debug(Objects.toString(quotaCache.getTableQuotaCache()));
|
||||||
|
LOG.debug(Objects.toString(quotaCache.getUserQuotaCache()));
|
||||||
|
LOG.debug(Objects.toString(quotaCache.getRegionServerQuotaCache()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void waitMinuteQuota() {
|
||||||
|
envEdge.incValue(70000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clearQuotaCache(HBaseTestingUtility testUtil) {
|
||||||
|
for (RegionServerThread rst : testUtil.getMiniHBaseCluster().getRegionServerThreads()) {
|
||||||
|
RegionServerRpcQuotaManager quotaManager =
|
||||||
|
rst.getRegionServer().getRegionServerRpcQuotaManager();
|
||||||
|
QuotaCache quotaCache = quotaManager.getQuotaCache();
|
||||||
|
quotaCache.getNamespaceQuotaCache().clear();
|
||||||
|
quotaCache.getTableQuotaCache().clear();
|
||||||
|
quotaCache.getUserQuotaCache().clear();
|
||||||
|
quotaCache.getRegionServerQuotaCache().clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,7 @@ java_import org.apache.hadoop.hbase.ServerName
|
||||||
java_import org.apache.hadoop.hbase.quotas.ThrottleType
|
java_import org.apache.hadoop.hbase.quotas.ThrottleType
|
||||||
java_import org.apache.hadoop.hbase.quotas.QuotaFilter
|
java_import org.apache.hadoop.hbase.quotas.QuotaFilter
|
||||||
java_import org.apache.hadoop.hbase.quotas.QuotaRetriever
|
java_import org.apache.hadoop.hbase.quotas.QuotaRetriever
|
||||||
|
java_import org.apache.hadoop.hbase.quotas.QuotaScope
|
||||||
java_import org.apache.hadoop.hbase.quotas.QuotaSettingsFactory
|
java_import org.apache.hadoop.hbase.quotas.QuotaSettingsFactory
|
||||||
java_import org.apache.hadoop.hbase.quotas.QuotaTableUtil
|
java_import org.apache.hadoop.hbase.quotas.QuotaTableUtil
|
||||||
java_import org.apache.hadoop.hbase.quotas.SpaceViolationPolicy
|
java_import org.apache.hadoop.hbase.quotas.SpaceViolationPolicy
|
||||||
|
@ -36,6 +37,9 @@ module HBaseQuotasConstants
|
||||||
REQUEST = 'REQUEST'.freeze
|
REQUEST = 'REQUEST'.freeze
|
||||||
WRITE = 'WRITE'.freeze
|
WRITE = 'WRITE'.freeze
|
||||||
READ = 'READ'.freeze
|
READ = 'READ'.freeze
|
||||||
|
SCOPE = 'SCOPE'.freeze
|
||||||
|
CLUSTER = 'CLUSTER'.freeze
|
||||||
|
MACHINE = 'MACHINE'.freeze
|
||||||
# Space quota constants
|
# Space quota constants
|
||||||
SPACE = 'SPACE'.freeze
|
SPACE = 'SPACE'.freeze
|
||||||
NO_INSERTS = 'NO_INSERTS'.freeze
|
NO_INSERTS = 'NO_INSERTS'.freeze
|
||||||
|
@ -60,30 +64,35 @@ module Hbase
|
||||||
type = args.fetch(THROTTLE_TYPE, REQUEST)
|
type = args.fetch(THROTTLE_TYPE, REQUEST)
|
||||||
args.delete(THROTTLE_TYPE)
|
args.delete(THROTTLE_TYPE)
|
||||||
type, limit, time_unit = _parse_limit(args.delete(LIMIT), ThrottleType, type)
|
type, limit, time_unit = _parse_limit(args.delete(LIMIT), ThrottleType, type)
|
||||||
|
scope = _parse_scope(args.fetch(SCOPE, MACHINE))
|
||||||
|
args.delete(SCOPE)
|
||||||
if args.key?(USER)
|
if args.key?(USER)
|
||||||
user = args.delete(USER)
|
user = args.delete(USER)
|
||||||
if args.key?(TABLE)
|
if args.key?(TABLE)
|
||||||
table = TableName.valueOf(args.delete(TABLE))
|
table = TableName.valueOf(args.delete(TABLE))
|
||||||
raise(ArgumentError, 'Unexpected arguments: ' + args.inspect) unless args.empty?
|
raise(ArgumentError, 'Unexpected arguments: ' + args.inspect) unless args.empty?
|
||||||
settings = QuotaSettingsFactory.throttleUser(user, table, type, limit, time_unit)
|
settings = QuotaSettingsFactory.throttleUser(user, table, type, limit, time_unit, scope)
|
||||||
elsif args.key?(NAMESPACE)
|
elsif args.key?(NAMESPACE)
|
||||||
namespace = args.delete(NAMESPACE)
|
namespace = args.delete(NAMESPACE)
|
||||||
raise(ArgumentError, 'Unexpected arguments: ' + args.inspect) unless args.empty?
|
raise(ArgumentError, 'Unexpected arguments: ' + args.inspect) unless args.empty?
|
||||||
settings = QuotaSettingsFactory.throttleUser(user, namespace, type, limit, time_unit)
|
settings = QuotaSettingsFactory.throttleUser(user, namespace, type, limit, time_unit, scope)
|
||||||
else
|
else
|
||||||
raise(ArgumentError, 'Unexpected arguments: ' + args.inspect) unless args.empty?
|
raise(ArgumentError, 'Unexpected arguments: ' + args.inspect) unless args.empty?
|
||||||
settings = QuotaSettingsFactory.throttleUser(user, type, limit, time_unit)
|
settings = QuotaSettingsFactory.throttleUser(user, type, limit, time_unit, scope)
|
||||||
end
|
end
|
||||||
elsif args.key?(TABLE)
|
elsif args.key?(TABLE)
|
||||||
table = TableName.valueOf(args.delete(TABLE))
|
table = TableName.valueOf(args.delete(TABLE))
|
||||||
raise(ArgumentError, 'Unexpected arguments: ' + args.inspect) unless args.empty?
|
raise(ArgumentError, 'Unexpected arguments: ' + args.inspect) unless args.empty?
|
||||||
settings = QuotaSettingsFactory.throttleTable(table, type, limit, time_unit)
|
settings = QuotaSettingsFactory.throttleTable(table, type, limit, time_unit, scope)
|
||||||
elsif args.key?(NAMESPACE)
|
elsif args.key?(NAMESPACE)
|
||||||
namespace = args.delete(NAMESPACE)
|
namespace = args.delete(NAMESPACE)
|
||||||
raise(ArgumentError, 'Unexpected arguments: ' + args.inspect) unless args.empty?
|
raise(ArgumentError, 'Unexpected arguments: ' + args.inspect) unless args.empty?
|
||||||
settings = QuotaSettingsFactory.throttleNamespace(namespace, type, limit, time_unit)
|
settings = QuotaSettingsFactory.throttleNamespace(namespace, type, limit, time_unit, scope)
|
||||||
elsif args.key?(REGIONSERVER)
|
elsif args.key?(REGIONSERVER)
|
||||||
# TODO: Setting specified region server quota isn't supported currently and using 'all' for all RS
|
# TODO: Setting specified region server quota isn't supported currently and using 'all' for all RS
|
||||||
|
if scope == QuotaScope.valueOf(CLUSTER)
|
||||||
|
raise(ArgumentError, 'Invalid region server throttle scope, must be MACHINE')
|
||||||
|
end
|
||||||
settings = QuotaSettingsFactory.throttleRegionServer('all', type, limit, time_unit)
|
settings = QuotaSettingsFactory.throttleRegionServer('all', type, limit, time_unit)
|
||||||
else
|
else
|
||||||
raise 'One of USER, TABLE, NAMESPACE or REGIONSERVER must be specified'
|
raise 'One of USER, TABLE, NAMESPACE or REGIONSERVER must be specified'
|
||||||
|
@ -325,6 +334,13 @@ module Hbase
|
||||||
end
|
end
|
||||||
value
|
value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def _parse_scope(scope_str)
|
||||||
|
scope_str = scope_str.upcase
|
||||||
|
return QuotaScope.valueOf(scope_str) if [CLUSTER, MACHINE].include?(scope_str)
|
||||||
|
unless raise(ArgumentError, 'Invalid throttle scope, must be either CLUSTER or MACHINE')
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
# rubocop:enable Metrics/ClassLength
|
# rubocop:enable Metrics/ClassLength
|
||||||
end
|
end
|
||||||
|
|
|
@ -26,14 +26,22 @@ Set a quota for a user, table, namespace or region server.
|
||||||
Syntax : set_quota TYPE => <type>, <args>
|
Syntax : set_quota TYPE => <type>, <args>
|
||||||
|
|
||||||
TYPE => THROTTLE
|
TYPE => THROTTLE
|
||||||
User can either set quota on read, write or on both the requests together(i.e., read+write).
|
1. User can set throttle quota for user, namespace, table, region server, user over namespace,
|
||||||
The read, write, or read+write(default throttle type) request limit can be expressed using
|
user over table by USER, NAMESPACE, TABLE, REGIONSERVER keys.
|
||||||
the form 100req/sec, 100req/min; the read, write, read+write(default throttle type) limit
|
Note: Setting specified region server quota isn't supported currently and using 'all' to
|
||||||
can be expressed using the form 100k/sec, 100M/min with (B, K, M, G, T, P) as valid size unit
|
represent all region servers.
|
||||||
; the read, write, read+write(default throttle type) limit can be expressed using the form
|
2. User can set throttle quota type either on read, write or on both the requests together(
|
||||||
100CU/sec as capacity unit. The valid time units are (sec, min, hour, day).
|
read+write, default throttle type) by THROTTLE_TYPE => READ, WRITE, REQUEST.
|
||||||
Currently the throttle limit is per machine - a limit of 100req/min
|
3. The request limit can be expressed using the form 100req/sec, 100req/min; or can be expressed
|
||||||
means that each machine can execute 100req/min.
|
using the form 100k/sec, 100M/min with (B, K, M, G, T, P) as valid size unit; or can be expressed
|
||||||
|
using the form 100CU/sec as capacity unit by LIMIT key.
|
||||||
|
The valid time units are (sec, min, hour, day).
|
||||||
|
4. User can set throttle scope to be either MACHINE(default throttle scope) or CLUSTER by
|
||||||
|
SCOPE => MACHINE, CLUSTER. MACHINE scope quota means the throttle limit is used by single
|
||||||
|
region server, CLUSTER scope quota means the throttle limit is shared by all region servers.
|
||||||
|
Region server throttle quota must be MACHINE scope.
|
||||||
|
Note: because currently use [ClusterLimit / RsNum] to divide cluster limit to machine limit,
|
||||||
|
so it's better to do not use cluster scope quota when you use rs group feature.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
|
@ -59,6 +67,9 @@ For example:
|
||||||
hbase> set_quota TYPE => THROTTLE, REGIONSERVER => 'all', THROTTLE_TYPE => WRITE, LIMIT => '20000req/sec'
|
hbase> set_quota TYPE => THROTTLE, REGIONSERVER => 'all', THROTTLE_TYPE => WRITE, LIMIT => '20000req/sec'
|
||||||
hbase> set_quota TYPE => THROTTLE, REGIONSERVER => 'all', LIMIT => NONE
|
hbase> set_quota TYPE => THROTTLE, REGIONSERVER => 'all', LIMIT => NONE
|
||||||
|
|
||||||
|
hbase> set_quota TYPE => THROTTLE, NAMESPACE => 'ns1', LIMIT => '10req/sec', SCOPE => CLUSTER
|
||||||
|
hbase> set_quota TYPE => THROTTLE, NAMESPACE => 'ns1', LIMIT => '10req/sec', SCOPE => MACHINE
|
||||||
|
|
||||||
hbase> set_quota USER => 'u1', GLOBAL_BYPASS => true
|
hbase> set_quota USER => 'u1', GLOBAL_BYPASS => true
|
||||||
|
|
||||||
TYPE => SPACE
|
TYPE => SPACE
|
||||||
|
|
|
@ -282,6 +282,23 @@ module Hbase
|
||||||
assert(output.include?('Previous exceed throttle quota enabled : true'))
|
assert(output.include?('Previous exceed throttle quota enabled : true'))
|
||||||
command(:set_quota, TYPE => THROTTLE, REGIONSERVER => 'all', LIMIT => NONE)
|
command(:set_quota, TYPE => THROTTLE, REGIONSERVER => 'all', LIMIT => NONE)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
define_test 'can set and remove CLUSTER scope quota' do
|
||||||
|
command(:set_quota, TYPE => THROTTLE, TABLE => @test_name, LIMIT => '100req/sec', SCOPE => CLUSTER)
|
||||||
|
output = capture_stdout { command(:list_quotas) }
|
||||||
|
assert(output.include?('LIMIT => 100req/sec'))
|
||||||
|
assert(output.include?('SCOPE => CLUSTER'))
|
||||||
|
|
||||||
|
command(:set_quota, TYPE => THROTTLE, TABLE => @test_name, LIMIT => '200req/sec', SCOPE => MACHINE)
|
||||||
|
output = capture_stdout { command(:list_quotas) }
|
||||||
|
assert(output.include?('1 row(s)'))
|
||||||
|
assert(output.include?('LIMIT => 200req/sec'))
|
||||||
|
assert(output.include?('SCOPE => MACHINE'))
|
||||||
|
|
||||||
|
command(:set_quota, TYPE => THROTTLE, TABLE => @test_name, LIMIT => NONE)
|
||||||
|
output = capture_stdout { command(:list_quotas) }
|
||||||
|
assert(output.include?('0 row(s)'))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
# rubocop:enable Metrics/ClassLength
|
# rubocop:enable Metrics/ClassLength
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue