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.AsyncConnectionConfiguration.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 073 .setQuota( 074 QuotaSettingsFactory.throttleUser(userName, ThrottleType.READ_NUMBER, 6, TimeUnit.MINUTES)) 075 .get(); 076 admin.setQuota( 077 QuotaSettingsFactory.throttleUser(userName, ThrottleType.WRITE_NUMBER, 12, TimeUnit.MINUTES)) 078 .get(); 079 admin.setQuota(QuotaSettingsFactory.bypassGlobals(userName, true)).get(); 080 081 int countThrottle = 0; 082 int countGlobalBypass = 0; 083 for (QuotaSettings settings : admin.getQuota(null).get()) { 084 switch (settings.getQuotaType()) { 085 case THROTTLE: 086 countThrottle++; 087 break; 088 case GLOBAL_BYPASS: 089 countGlobalBypass++; 090 break; 091 default: 092 fail("unexpected settings type: " + settings.getQuotaType()); 093 } 094 } 095 assertEquals(2, countThrottle); 096 assertEquals(1, countGlobalBypass); 097 098 admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName)).get(); 099 assertNumResults(1, null); 100 admin.setQuota(QuotaSettingsFactory.bypassGlobals(userName, false)).get(); 101 assertNumResults(0, null); 102 } 103 104 @Test 105 public void testQuotaRetrieverFilter() throws Exception { 106 TableName[] tables = new TableName[] { TableName.valueOf("T0"), TableName.valueOf("T01"), 107 TableName.valueOf("NS0:T2"), }; 108 String[] namespaces = new String[] { "NS0", "NS01", "NS2" }; 109 String[] users = new String[] { "User0", "User01", "User2" }; 110 111 for (String user : users) { 112 admin 113 .setQuota( 114 QuotaSettingsFactory.throttleUser(user, ThrottleType.REQUEST_NUMBER, 1, TimeUnit.MINUTES)) 115 .get(); 116 117 for (TableName table : tables) { 118 admin.setQuota(QuotaSettingsFactory.throttleUser(user, table, ThrottleType.REQUEST_NUMBER, 119 2, TimeUnit.MINUTES)).get(); 120 } 121 122 for (String ns : namespaces) { 123 admin.setQuota(QuotaSettingsFactory.throttleUser(user, ns, ThrottleType.REQUEST_NUMBER, 3, 124 TimeUnit.MINUTES)).get(); 125 } 126 } 127 assertNumResults(21, null); 128 129 for (TableName table : tables) { 130 admin.setQuota( 131 QuotaSettingsFactory.throttleTable(table, ThrottleType.REQUEST_NUMBER, 4, TimeUnit.MINUTES)) 132 .get(); 133 } 134 assertNumResults(24, null); 135 136 for (String ns : namespaces) { 137 admin.setQuota(QuotaSettingsFactory.throttleNamespace(ns, ThrottleType.REQUEST_NUMBER, 5, 138 TimeUnit.MINUTES)).get(); 139 } 140 assertNumResults(27, null); 141 142 assertNumResults(7, new QuotaFilter().setUserFilter("User0")); 143 assertNumResults(0, new QuotaFilter().setUserFilter("User")); 144 assertNumResults(21, new QuotaFilter().setUserFilter("User.*")); 145 assertNumResults(3, new QuotaFilter().setUserFilter("User.*").setTableFilter("T0")); 146 assertNumResults(3, new QuotaFilter().setUserFilter("User.*").setTableFilter("NS.*")); 147 assertNumResults(0, new QuotaFilter().setUserFilter("User.*").setTableFilter("T")); 148 assertNumResults(6, new QuotaFilter().setUserFilter("User.*").setTableFilter("T.*")); 149 assertNumResults(3, new QuotaFilter().setUserFilter("User.*").setNamespaceFilter("NS0")); 150 assertNumResults(0, new QuotaFilter().setUserFilter("User.*").setNamespaceFilter("NS")); 151 assertNumResults(9, new QuotaFilter().setUserFilter("User.*").setNamespaceFilter("NS.*")); 152 assertNumResults(6, 153 new QuotaFilter().setUserFilter("User.*").setTableFilter("T0").setNamespaceFilter("NS0")); 154 assertNumResults(1, new QuotaFilter().setTableFilter("T0")); 155 assertNumResults(0, new QuotaFilter().setTableFilter("T")); 156 assertNumResults(2, new QuotaFilter().setTableFilter("T.*")); 157 assertNumResults(3, new QuotaFilter().setTableFilter(".*T.*")); 158 assertNumResults(1, new QuotaFilter().setNamespaceFilter("NS0")); 159 assertNumResults(0, new QuotaFilter().setNamespaceFilter("NS")); 160 assertNumResults(3, new QuotaFilter().setNamespaceFilter("NS.*")); 161 162 for (String user : users) { 163 admin.setQuota(QuotaSettingsFactory.unthrottleUser(user)).get(); 164 for (TableName table : tables) { 165 admin.setQuota(QuotaSettingsFactory.unthrottleUser(user, table)).get(); 166 } 167 for (String ns : namespaces) { 168 admin.setQuota(QuotaSettingsFactory.unthrottleUser(user, ns)).get(); 169 } 170 } 171 assertNumResults(6, null); 172 173 for (TableName table : tables) { 174 admin.setQuota(QuotaSettingsFactory.unthrottleTable(table)).get(); 175 } 176 assertNumResults(3, null); 177 178 for (String ns : namespaces) { 179 admin.setQuota(QuotaSettingsFactory.unthrottleNamespace(ns)).get(); 180 } 181 assertNumResults(0, null); 182 } 183 184 @Test 185 public void testSwitchRpcThrottle() throws Exception { 186 CompletableFuture<Boolean> future1 = ASYNC_CONN.getAdmin().switchRpcThrottle(true); 187 assertEquals(true, future1.get().booleanValue()); 188 CompletableFuture<Boolean> future2 = ASYNC_CONN.getAdmin().isRpcThrottleEnabled(); 189 assertEquals(true, future2.get().booleanValue()); 190 } 191 192 @Test 193 public void testSwitchExceedThrottleQuota() throws Exception { 194 AsyncAdmin admin = ASYNC_CONN.getAdmin(); 195 assertEquals(false, admin.exceedThrottleQuotaSwitch(false).get().booleanValue()); 196 } 197 198 private void assertNumResults(int expected, final QuotaFilter filter) throws Exception { 199 assertEquals(expected, countResults(filter)); 200 } 201 202 private int countResults(final QuotaFilter filter) throws Exception { 203 int count = 0; 204 for (QuotaSettings settings : admin.getQuota(filter).get()) { 205 LOG.debug(Objects.toString(settings)); 206 count++; 207 } 208 return count; 209 } 210}