1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.rsgroup;
19
20 import static org.junit.Assert.assertTrue;
21
22 import java.io.IOException;
23 import java.util.Collections;
24
25 import org.apache.hadoop.hbase.HBaseTestingUtility;
26 import org.apache.hadoop.hbase.HColumnDescriptor;
27 import org.apache.hadoop.hbase.HConstants;
28 import org.apache.hadoop.hbase.HRegionInfo;
29 import org.apache.hadoop.hbase.HTableDescriptor;
30 import org.apache.hadoop.hbase.NamespaceDescriptor;
31 import org.apache.hadoop.hbase.ProcedureInfo;
32 import org.apache.hadoop.hbase.ServerName;
33 import org.apache.hadoop.hbase.TableName;
34 import org.apache.hadoop.hbase.Waiter;
35 import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
36 import org.apache.hadoop.hbase.master.ServerManager;
37 import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;
38 import org.apache.hadoop.hbase.master.snapshot.SnapshotManager;
39 import org.apache.hadoop.hbase.net.Address;
40 import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
41 import org.apache.hadoop.hbase.protobuf.generated.ProcedureProtos;
42 import org.apache.hadoop.hbase.testclassification.MediumTests;
43 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
44 import org.apache.hadoop.hbase.util.JVMClusterUtil;
45 import org.apache.hadoop.hbase.util.Threads;
46 import org.junit.After;
47 import org.junit.AfterClass;
48 import org.junit.Before;
49 import org.junit.BeforeClass;
50 import org.junit.Test;
51 import org.junit.experimental.categories.Category;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54
55 @Category({ MediumTests.class })
56 public class TestRSGroupsFallback extends TestRSGroupsBase {
57 protected static final Logger LOG = LoggerFactory.getLogger(TestRSGroupsFallback.class);
58
59 private static final String FALLBACK_GROUP = "fallback";
60
61 @BeforeClass
62 public static void setUp() throws Exception {
63 TEST_UTIL = new HBaseTestingUtility();
64 TEST_UTIL.getConfiguration().setBoolean(RSGroupBasedLoadBalancer.FALLBACK_GROUP_ENABLE_KEY,
65 true);
66 TEST_UTIL.getConfiguration().setFloat(
67 "hbase.master.balancer.stochastic.tableSkewCost", 6000);
68 TEST_UTIL.getConfiguration().set(
69 HConstants.HBASE_MASTER_LOADBALANCER_CLASS,
70 RSGroupBasedLoadBalancer.class.getName());
71 TEST_UTIL.getConfiguration().set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY,
72 RSGroupAdminEndpoint.class.getName() + "," + CPMasterObserver.class.getName());
73 TEST_UTIL.getConfiguration().setBoolean(
74 HConstants.ZOOKEEPER_USEMULTI,
75 true);
76 TEST_UTIL.startMiniCluster(NUM_SLAVES_BASE - 1);
77 TEST_UTIL.getConfiguration().setInt(
78 ServerManager.WAIT_ON_REGIONSERVERS_MINTOSTART,
79 NUM_SLAVES_BASE - 1);
80 TEST_UTIL.getConfiguration().setBoolean(SnapshotManager.HBASE_SNAPSHOT_ENABLED, true);
81 initialize();
82 master.balanceSwitch(true);
83 }
84
85 @AfterClass
86 public static void tearDown() throws Exception {
87 tearDownAfterClass();
88 }
89
90 @Before
91 public void beforeMethod() throws Exception {
92 setUpBeforeMethod();
93 }
94
95 @After
96 public void afterMethod() throws Exception {
97 tearDownAfterMethod();
98 }
99
100 @Test
101 public void testFallback() throws Exception {
102
103 addGroup(rsGroupAdmin, FALLBACK_GROUP, 1);
104
105 String groupName = "appInfo";
106 RSGroupInfo appInfo = addGroup(rsGroupAdmin, groupName, 1);
107 final TableName tableName = TableName.valueOf(tablePrefix + "_ns", "_testFallback");
108 admin.createNamespace(
109 NamespaceDescriptor.create(tableName.getNamespaceAsString())
110 .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, appInfo.getName()).build());
111 final HTableDescriptor desc = new HTableDescriptor(tableName);
112 desc.addFamily(new HColumnDescriptor("f"));
113 admin.createTable(desc);
114
115 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
116 @Override
117 public boolean evaluate() throws Exception {
118 return getTableRegionMap().get(desc.getTableName()) != null;
119 }
120 });
121 TEST_UTIL.waitUntilAllRegionsAssigned(tableName);
122
123
124 crashRsInGroup(groupName);
125 assertRegionsInGroup(tableName, RSGroupInfo.DEFAULT_GROUP);
126
127
128 crashRsInGroup(RSGroupInfo.DEFAULT_GROUP);
129 assertRegionsInGroup(tableName, FALLBACK_GROUP);
130
131
132 JVMClusterUtil.RegionServerThread t =
133 TEST_UTIL.getMiniHBaseCluster().startRegionServerAndWait(60000);
134 assertTrue(master.balance());
135 assertRegionsInGroup(tableName, RSGroupInfo.DEFAULT_GROUP);
136
137
138 JVMClusterUtil.RegionServerThread t1 =
139 TEST_UTIL.getMiniHBaseCluster().startRegionServerAndWait(60000);
140 rsGroupAdmin.moveServers(Collections.singleton(t.getRegionServer().getServerName()
141 .getAddress()), groupName);
142 assertTrue(master.balance());
143 assertRegionsInGroup(tableName, groupName);
144
145 TEST_UTIL.getMiniHBaseCluster().killRegionServer(t.getRegionServer().getServerName());
146 TEST_UTIL.getMiniHBaseCluster().killRegionServer(t1.getRegionServer().getServerName());
147
148 TEST_UTIL.deleteTable(tableName);
149 }
150
151 private void assertRegionsInGroup(TableName table, String group) throws IOException {
152 ProcedureExecutor<MasterProcedureEnv> procExecutor = TEST_UTIL.getMiniHBaseCluster()
153 .getMaster().getMasterProcedureExecutor();
154 for (ProcedureInfo procInfo: procExecutor.listProcedures()) {
155 LOG.debug("Waiting for " + procInfo.getProcName() + " " + procInfo.toString());
156 waitProcedure(procExecutor, procInfo, 10000);
157 }
158 RSGroupInfo rsGroup = rsGroupAdmin.getRSGroupInfo(group);
159 for (HRegionInfo region: master.getAssignmentManager().getRegionStates()
160 .getRegionsOfTable(table)) {
161 Address regionOnServer = master.getAssignmentManager().getRegionStates()
162 .getRegionAssignments().get(region).getAddress();
163 assertTrue(rsGroup.getServers().contains(regionOnServer));
164 }
165 }
166
167 private void crashRsInGroup(String groupName) throws Exception {
168 for (Address server : rsGroupAdmin.getRSGroupInfo(groupName).getServers()) {
169 final ServerName sn = getServerName(server);
170 TEST_UTIL.getMiniHBaseCluster().killRegionServer(sn);
171 TEST_UTIL.waitFor(60000, new Waiter.Predicate<Exception>() {
172 @Override
173 public boolean evaluate() {
174 return master.getServerManager().isServerDead(sn);
175 }
176 });
177 }
178 Threads.sleep(1000);
179 TEST_UTIL.waitUntilNoRegionsInTransition(60000);
180 }
181
182 private void waitProcedure(ProcedureExecutor<MasterProcedureEnv> procExecutor,
183 ProcedureInfo procInfo, long timeout) {
184 long start = EnvironmentEdgeManager.currentTime();
185 while ((EnvironmentEdgeManager.currentTime() - start) < timeout) {
186 if (procInfo.getProcState() == ProcedureProtos.ProcedureState.INITIALIZING ||
187 (procExecutor.isRunning() && !procExecutor.isFinished(procInfo.getProcId()))) {
188 Threads.sleep(1000);
189 } else {
190 break;
191 }
192 }
193 }
194 }