001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.client; 019 020import static org.apache.hadoop.hbase.client.AsyncProcess.START_LOG_ERRORS_AFTER_COUNT_KEY; 021import static org.junit.Assert.assertEquals; 022import static org.junit.Assert.fail; 023 024import java.util.Objects; 025import java.util.concurrent.CompletableFuture; 026import java.util.concurrent.TimeUnit; 027import org.apache.hadoop.hbase.HBaseClassTestRule; 028import org.apache.hadoop.hbase.HConstants; 029import org.apache.hadoop.hbase.TableName; 030import org.apache.hadoop.hbase.quotas.QuotaCache; 031import org.apache.hadoop.hbase.quotas.QuotaFilter; 032import org.apache.hadoop.hbase.quotas.QuotaSettings; 033import org.apache.hadoop.hbase.quotas.QuotaSettingsFactory; 034import org.apache.hadoop.hbase.quotas.QuotaTableUtil; 035import org.apache.hadoop.hbase.quotas.QuotaUtil; 036import org.apache.hadoop.hbase.quotas.ThrottleType; 037import org.apache.hadoop.hbase.security.User; 038import org.apache.hadoop.hbase.testclassification.ClientTests; 039import org.apache.hadoop.hbase.testclassification.MediumTests; 040import org.junit.BeforeClass; 041import org.junit.ClassRule; 042import org.junit.Test; 043import org.junit.experimental.categories.Category; 044import org.junit.runner.RunWith; 045import org.junit.runners.Parameterized; 046 047@RunWith(Parameterized.class) 048@Category({ ClientTests.class, MediumTests.class }) 049public class TestAsyncQuotaAdminApi extends TestAsyncAdminBase { 050 051 @ClassRule 052 public static final HBaseClassTestRule CLASS_RULE = 053 HBaseClassTestRule.forClass(TestAsyncQuotaAdminApi.class); 054 055 @BeforeClass 056 public static void setUpBeforeClass() throws Exception { 057 TEST_UTIL.getConfiguration().setBoolean(QuotaUtil.QUOTA_CONF_KEY, true); 058 TEST_UTIL.getConfiguration().setInt(QuotaCache.REFRESH_CONF_KEY, 2000); 059 TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, 60000); 060 TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_OPERATION_TIMEOUT, 120000); 061 TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 2); 062 TEST_UTIL.getConfiguration().setInt(START_LOG_ERRORS_AFTER_COUNT_KEY, 0); 063 TEST_UTIL.startMiniCluster(1); 064 TEST_UTIL.waitTableAvailable(QuotaTableUtil.QUOTA_TABLE_NAME); 065 ASYNC_CONN = ConnectionFactory.createAsyncConnection(TEST_UTIL.getConfiguration()).get(); 066 } 067 068 @Test 069 public void testThrottleType() throws Exception { 070 String userName = User.getCurrent().getShortName(); 071 072 admin.setQuota( 073 QuotaSettingsFactory.throttleUser(userName, ThrottleType.READ_NUMBER, 6, TimeUnit.MINUTES)) 074 .get(); 075 admin.setQuota( 076 QuotaSettingsFactory.throttleUser(userName, ThrottleType.WRITE_NUMBER, 12, TimeUnit.MINUTES)) 077 .get(); 078 admin.setQuota(QuotaSettingsFactory.bypassGlobals(userName, true)).get(); 079 080 int countThrottle = 0; 081 int countGlobalBypass = 0; 082 for (QuotaSettings settings : admin.getQuota(null).get()) { 083 switch (settings.getQuotaType()) { 084 case THROTTLE: 085 countThrottle++; 086 break; 087 case GLOBAL_BYPASS: 088 countGlobalBypass++; 089 break; 090 default: 091 fail("unexpected settings type: " + settings.getQuotaType()); 092 } 093 } 094 assertEquals(2, countThrottle); 095 assertEquals(1, countGlobalBypass); 096 097 admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName)).get(); 098 assertNumResults(1, null); 099 admin.setQuota(QuotaSettingsFactory.bypassGlobals(userName, false)).get(); 100 assertNumResults(0, null); 101 } 102 103 @Test 104 public void testQuotaRetrieverFilter() throws Exception { 105 TableName[] tables = new TableName[] { TableName.valueOf("T0"), TableName.valueOf("T01"), 106 TableName.valueOf("NS0:T2"), }; 107 String[] namespaces = new String[] { "NS0", "NS01", "NS2" }; 108 String[] users = new String[] { "User0", "User01", "User2" }; 109 110 for (String user : users) { 111 admin.setQuota( 112 QuotaSettingsFactory.throttleUser(user, ThrottleType.REQUEST_NUMBER, 1, TimeUnit.MINUTES)) 113 .get(); 114 115 for (TableName table : tables) { 116 admin.setQuota(QuotaSettingsFactory.throttleUser(user, table, ThrottleType.REQUEST_NUMBER, 117 2, TimeUnit.MINUTES)).get(); 118 } 119 120 for (String ns : namespaces) { 121 admin.setQuota(QuotaSettingsFactory.throttleUser(user, ns, ThrottleType.REQUEST_NUMBER, 3, 122 TimeUnit.MINUTES)).get(); 123 } 124 } 125 assertNumResults(21, null); 126 127 for (TableName table : tables) { 128 admin.setQuota( 129 QuotaSettingsFactory.throttleTable(table, ThrottleType.REQUEST_NUMBER, 4, TimeUnit.MINUTES)) 130 .get(); 131 } 132 assertNumResults(24, null); 133 134 for (String ns : namespaces) { 135 admin.setQuota(QuotaSettingsFactory.throttleNamespace(ns, ThrottleType.REQUEST_NUMBER, 5, 136 TimeUnit.MINUTES)).get(); 137 } 138 assertNumResults(27, null); 139 140 assertNumResults(7, new QuotaFilter().setUserFilter("User0")); 141 assertNumResults(0, new QuotaFilter().setUserFilter("User")); 142 assertNumResults(21, new QuotaFilter().setUserFilter("User.*")); 143 assertNumResults(3, new QuotaFilter().setUserFilter("User.*").setTableFilter("T0")); 144 assertNumResults(3, new QuotaFilter().setUserFilter("User.*").setTableFilter("NS.*")); 145 assertNumResults(0, new QuotaFilter().setUserFilter("User.*").setTableFilter("T")); 146 assertNumResults(6, new QuotaFilter().setUserFilter("User.*").setTableFilter("T.*")); 147 assertNumResults(3, new QuotaFilter().setUserFilter("User.*").setNamespaceFilter("NS0")); 148 assertNumResults(0, new QuotaFilter().setUserFilter("User.*").setNamespaceFilter("NS")); 149 assertNumResults(9, new QuotaFilter().setUserFilter("User.*").setNamespaceFilter("NS.*")); 150 assertNumResults(6, 151 new QuotaFilter().setUserFilter("User.*").setTableFilter("T0").setNamespaceFilter("NS0")); 152 assertNumResults(1, new QuotaFilter().setTableFilter("T0")); 153 assertNumResults(0, new QuotaFilter().setTableFilter("T")); 154 assertNumResults(2, new QuotaFilter().setTableFilter("T.*")); 155 assertNumResults(3, new QuotaFilter().setTableFilter(".*T.*")); 156 assertNumResults(1, new QuotaFilter().setNamespaceFilter("NS0")); 157 assertNumResults(0, new QuotaFilter().setNamespaceFilter("NS")); 158 assertNumResults(3, new QuotaFilter().setNamespaceFilter("NS.*")); 159 160 for (String user : users) { 161 admin.setQuota(QuotaSettingsFactory.unthrottleUser(user)).get(); 162 for (TableName table : tables) { 163 admin.setQuota(QuotaSettingsFactory.unthrottleUser(user, table)).get(); 164 } 165 for (String ns : namespaces) { 166 admin.setQuota(QuotaSettingsFactory.unthrottleUser(user, ns)).get(); 167 } 168 } 169 assertNumResults(6, null); 170 171 for (TableName table : tables) { 172 admin.setQuota(QuotaSettingsFactory.unthrottleTable(table)).get(); 173 } 174 assertNumResults(3, null); 175 176 for (String ns : namespaces) { 177 admin.setQuota(QuotaSettingsFactory.unthrottleNamespace(ns)).get(); 178 } 179 assertNumResults(0, null); 180 } 181 182 @Test 183 public void testSwitchRpcThrottle() throws Exception { 184 CompletableFuture<Boolean> future1 = ASYNC_CONN.getAdmin().switchRpcThrottle(true); 185 assertEquals(true, future1.get().booleanValue()); 186 CompletableFuture<Boolean> future2 = ASYNC_CONN.getAdmin().isRpcThrottleEnabled(); 187 assertEquals(true, future2.get().booleanValue()); 188 } 189 190 @Test 191 public void testSwitchExceedThrottleQuota() throws Exception { 192 AsyncAdmin admin = ASYNC_CONN.getAdmin(); 193 assertEquals(false, admin.exceedThrottleQuotaSwitch(false).get().booleanValue()); 194 } 195 196 private void assertNumResults(int expected, final QuotaFilter filter) throws Exception { 197 assertEquals(expected, countResults(filter)); 198 } 199 200 private int countResults(final QuotaFilter filter) throws Exception { 201 int count = 0; 202 for (QuotaSettings settings : admin.getQuota(filter).get()) { 203 LOG.debug(Objects.toString(settings)); 204 count++; 205 } 206 return count; 207 } 208}