View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.master;
20  
21  import static org.junit.Assert.assertTrue;
22  
23  import java.io.IOException;
24  import java.util.concurrent.atomic.AtomicBoolean;
25  import java.util.concurrent.atomic.AtomicInteger;
26  
27  import org.apache.hadoop.hbase.HBaseTestingUtility;
28  import org.apache.hadoop.hbase.HConstants;
29  import org.apache.hadoop.hbase.HRegionInfo;
30  import org.apache.hadoop.hbase.TableName;
31  import org.apache.hadoop.hbase.regionserver.HRegionServer;
32  import org.apache.hadoop.hbase.testclassification.MasterTests;
33  import org.apache.hadoop.hbase.testclassification.MediumTests;
34  import org.apache.hadoop.hbase.util.Bytes;
35  import org.junit.After;
36  import org.junit.Before;
37  import org.junit.Test;
38  import org.junit.experimental.categories.Category;
39  
40  @Category({MasterTests.class, MediumTests.class})
41  public class TestMasterBalanceThrottling {
42    private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
43    private static final byte[] FAMILYNAME = Bytes.toBytes("fam");
44  
45    @Before
46    public void setupConfiguration() {
47      TEST_UTIL.getConfiguration().set(HConstants.HBASE_MASTER_LOADBALANCER_CLASS,
48          "org.apache.hadoop.hbase.master.balancer.SimpleLoadBalancer");
49    }
50  
51    @After
52    public void shutdown() throws Exception {
53      TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_BALANCER_MAX_BALANCING,
54        HConstants.DEFAULT_HBASE_BALANCER_PERIOD);
55      TEST_UTIL.getConfiguration().setDouble(HConstants.HBASE_MASTER_BALANCER_MAX_RIT_PERCENT,
56        HConstants.DEFAULT_HBASE_MASTER_BALANCER_MAX_RIT_PERCENT);
57      TEST_UTIL.shutdownMiniCluster();
58    }
59  
60    @Test(timeout = 60000)
61    public void testThrottlingByBalanceInterval() throws Exception {
62      // Use default config and start a cluster of two regionservers.
63      TEST_UTIL.startMiniCluster(2);
64  
65      TableName tableName = createTable("testNoThrottling");
66      final HMaster master = TEST_UTIL.getHBaseCluster().getMaster();
67  
68      // Default max balancing time is 300000 ms and there are 50 regions to balance
69      // The balance interval is 6000 ms, much longger than the normal region in transition duration
70      // So the master can balance the region one by one
71      unbalance(master, tableName);
72      AtomicInteger maxCount = new AtomicInteger(0);
73      AtomicBoolean stop = new AtomicBoolean(false);
74      Thread checker = startBalancerChecker(master, maxCount, stop);
75      master.balance();
76      stop.set(true);
77      checker.interrupt();
78      checker.join();
79      assertTrue("max regions in transition: " + maxCount.get(), maxCount.get() == 1);
80  
81      TEST_UTIL.deleteTable(tableName);
82    }
83  
84    @Test(timeout = 60000)
85    public void testThrottlingByMaxRitPercent() throws Exception {
86      // Set max balancing time to 500 ms and max percent of regions in transition to 0.05
87      TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_BALANCER_MAX_BALANCING, 500);
88      TEST_UTIL.getConfiguration().setDouble(HConstants.HBASE_MASTER_BALANCER_MAX_RIT_PERCENT, 0.05);
89      TEST_UTIL.startMiniCluster(2);
90  
91      TableName tableName = createTable("testThrottlingByMaxRitPercent");
92      final HMaster master = TEST_UTIL.getHBaseCluster().getMaster();
93  
94      unbalance(master, tableName);
95      AtomicInteger maxCount = new AtomicInteger(0);
96      AtomicBoolean stop = new AtomicBoolean(false);
97      Thread checker = startBalancerChecker(master, maxCount, stop);
98      master.balance();
99      stop.set(true);
100     checker.interrupt();
101     checker.join();
102     // The max number of regions in transition is 100 * 0.05 = 5
103     assertTrue("max regions in transition: " + maxCount.get(), maxCount.get() == 5);
104 
105     TEST_UTIL.deleteTable(tableName);
106   }
107 
108   private TableName createTable(String table) throws IOException {
109     TableName tableName = TableName.valueOf(table);
110     byte[] startKey = new byte[] { 0x00 };
111     byte[] stopKey = new byte[] { 0x7f };
112     TEST_UTIL.createTable(tableName, new byte[][] { FAMILYNAME }, 1, startKey, stopKey,
113       100);
114     return tableName;
115   }
116 
117   private Thread startBalancerChecker(final HMaster master, final AtomicInteger maxCount,
118       final AtomicBoolean stop) {
119     Runnable checker = new Runnable() {
120       @Override
121       public void run() {
122         while (!stop.get()) {
123           maxCount.set(Math.max(maxCount.get(), master.getAssignmentManager().getRegionStates()
124               .getRegionsInTransitionCount()));
125           try {
126             Thread.sleep(10);
127           } catch (InterruptedException e) {
128             e.printStackTrace();
129           }
130         }
131       }
132     };
133     Thread thread = new Thread(checker);
134     thread.start();
135     return thread;
136   }
137 
138   private void unbalance(HMaster master, TableName tableName) throws Exception {
139     while (master.getAssignmentManager().getRegionStates().getRegionsInTransitionCount() > 0) {
140       Thread.sleep(100);
141     }
142     HRegionServer biasedServer = TEST_UTIL.getMiniHBaseCluster().getRegionServer(0);
143     for (HRegionInfo regionInfo : TEST_UTIL.getHBaseAdmin().getTableRegions(tableName)) {
144       master.move(regionInfo.getEncodedNameAsBytes(),
145         Bytes.toBytes(biasedServer.getServerName().getServerName()));
146     }
147     while (master.getAssignmentManager().getRegionStates().getRegionsInTransitionCount() > 0) {
148       Thread.sleep(100);
149     }
150   }
151 }