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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 package org
.apache
.hadoop
.hbase
.master
;
22 import java
.io
.IOException
;
23 import java
.util
.List
;
25 import org
.apache
.hadoop
.conf
.Configuration
;
26 import org
.apache
.hadoop
.hbase
.HConstants
;
27 import org
.apache
.hadoop
.hbase
.LocalHBaseCluster
;
28 import org
.apache
.hadoop
.hbase
.MasterNotRunningException
;
29 import org
.apache
.hadoop
.hbase
.ZNodeClearer
;
30 import org
.apache
.hadoop
.hbase
.ZooKeeperConnectionException
;
31 import org
.apache
.hadoop
.hbase
.trace
.TraceUtil
;
32 import org
.apache
.yetus
.audience
.InterfaceAudience
;
33 import org
.apache
.hadoop
.hbase
.client
.Admin
;
34 import org
.apache
.hadoop
.hbase
.client
.Connection
;
35 import org
.apache
.hadoop
.hbase
.client
.ConnectionFactory
;
36 import org
.apache
.hadoop
.hbase
.regionserver
.HRegionServer
;
37 import org
.apache
.hadoop
.hbase
.util
.JVMClusterUtil
;
38 import org
.apache
.hadoop
.hbase
.util
.ServerCommandLine
;
39 import org
.apache
.hadoop
.hbase
.zookeeper
.MiniZooKeeperCluster
;
40 import org
.apache
.hadoop
.hbase
.zookeeper
.ZKUtil
;
41 import org
.apache
.hadoop
.metrics2
.lib
.DefaultMetricsSystem
;
42 import org
.apache
.zookeeper
.KeeperException
;
43 import org
.slf4j
.Logger
;
44 import org
.slf4j
.LoggerFactory
;
46 import org
.apache
.hbase
.thirdparty
.org
.apache
.commons
.cli
.CommandLine
;
47 import org
.apache
.hbase
.thirdparty
.org
.apache
.commons
.cli
.GnuParser
;
48 import org
.apache
.hbase
.thirdparty
.org
.apache
.commons
.cli
.Options
;
49 import org
.apache
.hbase
.thirdparty
.org
.apache
.commons
.cli
.ParseException
;
51 @InterfaceAudience.Private
52 public class HMasterCommandLine
extends ServerCommandLine
{
53 private static final Logger LOG
= LoggerFactory
.getLogger(HMasterCommandLine
.class);
55 private static final String USAGE
=
56 "Usage: Master [opts] start|stop|clear\n" +
57 " start Start Master. If local mode, start Master and RegionServer in same JVM\n" +
58 " stop Start cluster shutdown; Master signals RegionServer shutdown\n" +
59 " clear Delete the master znode in ZooKeeper after a master crashes\n "+
60 " where [opts] are:\n" +
61 " --minRegionServers=<servers> Minimum RegionServers needed to host user tables.\n" +
62 " --localRegionServers=<servers> " +
63 "RegionServers to start in master process when in standalone mode.\n" +
64 " --masters=<servers> Masters to start in this process.\n" +
65 " --backup Master should start in backup mode";
67 private final Class
<?
extends HMaster
> masterClass
;
69 public HMasterCommandLine(Class
<?
extends HMaster
> masterClass
) {
70 this.masterClass
= masterClass
;
74 protected String
getUsage() {
79 public int run(String args
[]) throws Exception
{
80 Options opt
= new Options();
81 opt
.addOption("localRegionServers", true,
82 "RegionServers to start in master process when running standalone");
83 opt
.addOption("masters", true, "Masters to start in this process");
84 opt
.addOption("minRegionServers", true, "Minimum RegionServers needed to host user tables");
85 opt
.addOption("backup", false, "Do not try to become HMaster until the primary fails");
89 cmd
= new GnuParser().parse(opt
, args
);
90 } catch (ParseException e
) {
91 LOG
.error("Could not parse: ", e
);
97 if (cmd
.hasOption("minRegionServers")) {
98 String val
= cmd
.getOptionValue("minRegionServers");
99 getConf().setInt("hbase.regions.server.count.min",
100 Integer
.parseInt(val
));
101 LOG
.debug("minRegionServers set to " + val
);
104 // minRegionServers used to be minServers. Support it too.
105 if (cmd
.hasOption("minServers")) {
106 String val
= cmd
.getOptionValue("minServers");
107 getConf().setInt("hbase.regions.server.count.min", Integer
.parseInt(val
));
108 LOG
.debug("minServers set to " + val
);
111 // check if we are the backup master - override the conf if so
112 if (cmd
.hasOption("backup")) {
113 getConf().setBoolean(HConstants
.MASTER_TYPE_BACKUP
, true);
116 // How many regionservers to startup in this process (we run regionservers in same process as
117 // master when we are in local/standalone mode. Useful testing)
118 if (cmd
.hasOption("localRegionServers")) {
119 String val
= cmd
.getOptionValue("localRegionServers");
120 getConf().setInt("hbase.regionservers", Integer
.parseInt(val
));
121 LOG
.debug("localRegionServers set to " + val
);
123 // How many masters to startup inside this process; useful testing
124 if (cmd
.hasOption("masters")) {
125 String val
= cmd
.getOptionValue("masters");
126 getConf().setInt("hbase.masters", Integer
.parseInt(val
));
127 LOG
.debug("masters set to " + val
);
130 @SuppressWarnings("unchecked")
131 List
<String
> remainingArgs
= cmd
.getArgList();
132 if (remainingArgs
.size() != 1) {
137 String command
= remainingArgs
.get(0);
139 if ("start".equals(command
)) {
140 return startMaster();
141 } else if ("stop".equals(command
)) {
143 } else if ("clear".equals(command
)) {
144 return (ZNodeClearer
.clear(getConf()) ?
0 : 1);
146 usage("Invalid command: " + command
);
151 private int startMaster() {
152 Configuration conf
= getConf();
153 TraceUtil
.initTracer(conf
);
156 // If 'local', defer to LocalHBaseCluster instance. Starts master
157 // and regionserver both in the one JVM.
158 if (LocalHBaseCluster
.isLocal(conf
)) {
159 DefaultMetricsSystem
.setMiniClusterMode(true);
160 final MiniZooKeeperCluster zooKeeperCluster
= new MiniZooKeeperCluster(conf
);
161 File zkDataPath
= new File(conf
.get(HConstants
.ZOOKEEPER_DATA_DIR
));
163 // find out the default client port
164 int zkClientPort
= 0;
166 // If the zookeeper client port is specified in server quorum, use it.
167 String zkserver
= conf
.get(HConstants
.ZOOKEEPER_QUORUM
);
168 if (zkserver
!= null) {
169 String
[] zkservers
= zkserver
.split(",");
171 if (zkservers
.length
> 1) {
172 // In local mode deployment, we have the master + a region server and zookeeper server
173 // started in the same process. Therefore, we only support one zookeeper server.
174 String errorMsg
= "Could not start ZK with " + zkservers
.length
+
175 " ZK servers in local mode deployment. Aborting as clients (e.g. shell) will not "
176 + "be able to find this ZK quorum.";
177 System
.err
.println(errorMsg
);
178 throw new IOException(errorMsg
);
181 String
[] parts
= zkservers
[0].split(":");
183 if (parts
.length
== 2) {
184 // the second part is the client port
185 zkClientPort
= Integer
.parseInt(parts
[1]);
188 // If the client port could not be find in server quorum conf, try another conf
189 if (zkClientPort
== 0) {
190 zkClientPort
= conf
.getInt(HConstants
.ZOOKEEPER_CLIENT_PORT
, 0);
191 // The client port has to be set by now; if not, throw exception.
192 if (zkClientPort
== 0) {
193 throw new IOException("No config value for " + HConstants
.ZOOKEEPER_CLIENT_PORT
);
196 zooKeeperCluster
.setDefaultClientPort(zkClientPort
);
197 // set the ZK tick time if specified
198 int zkTickTime
= conf
.getInt(HConstants
.ZOOKEEPER_TICK_TIME
, 0);
199 if (zkTickTime
> 0) {
200 zooKeeperCluster
.setTickTime(zkTickTime
);
203 // login the zookeeper server principal (if using security)
204 ZKUtil
.loginServer(conf
, HConstants
.ZK_SERVER_KEYTAB_FILE
,
205 HConstants
.ZK_SERVER_KERBEROS_PRINCIPAL
, null);
206 int localZKClusterSessionTimeout
=
207 conf
.getInt(HConstants
.ZK_SESSION_TIMEOUT
+ ".localHBaseCluster", 10*1000);
208 conf
.setInt(HConstants
.ZK_SESSION_TIMEOUT
, localZKClusterSessionTimeout
);
209 LOG
.info("Starting a zookeeper cluster");
210 int clientPort
= zooKeeperCluster
.startup(zkDataPath
);
211 if (clientPort
!= zkClientPort
) {
212 String errorMsg
= "Could not start ZK at requested port of " +
213 zkClientPort
+ ". ZK was started at port: " + clientPort
+
214 ". Aborting as clients (e.g. shell) will not be able to find " +
216 System
.err
.println(errorMsg
);
217 throw new IOException(errorMsg
);
219 conf
.set(HConstants
.ZOOKEEPER_CLIENT_PORT
, Integer
.toString(clientPort
));
221 // Need to have the zk cluster shutdown when master is shutdown.
222 // Run a subclass that does the zk cluster shutdown on its way out.
223 int mastersCount
= conf
.getInt("hbase.masters", 1);
224 int regionServersCount
= conf
.getInt("hbase.regionservers", 1);
225 // Set start timeout to 5 minutes for cmd line start operations
226 conf
.setIfUnset("hbase.master.start.timeout.localHBaseCluster", "300000");
227 LOG
.info("Starting up instance of localHBaseCluster; master=" + mastersCount
+
228 ", regionserversCount=" + regionServersCount
);
229 LocalHBaseCluster cluster
= new LocalHBaseCluster(conf
, mastersCount
, regionServersCount
,
230 LocalHMaster
.class, HRegionServer
.class);
231 ((LocalHMaster
)cluster
.getMaster(0)).setZKCluster(zooKeeperCluster
);
233 waitOnMasterThreads(cluster
);
235 logProcessInfo(getConf());
236 HMaster master
= HMaster
.constructMaster(masterClass
, conf
);
237 if (master
.isStopped()) {
238 LOG
.info("Won't bring the Master up as a shutdown is requested");
243 if(master
.isAborted())
244 throw new RuntimeException("HMaster Aborted");
246 } catch (Throwable t
) {
247 LOG
.error("Master exiting", t
);
253 @SuppressWarnings("resource")
254 private int stopMaster() {
255 Configuration conf
= getConf();
256 // Don't try more than once
257 conf
.setInt(HConstants
.HBASE_CLIENT_RETRIES_NUMBER
, 0);
258 try (Connection connection
= ConnectionFactory
.createConnection(conf
)) {
259 try (Admin admin
= connection
.getAdmin()) {
261 } catch (Throwable t
) {
262 LOG
.error("Failed to stop master", t
);
265 } catch (MasterNotRunningException e
) {
266 LOG
.error("Master not running");
268 } catch (ZooKeeperConnectionException e
) {
269 LOG
.error("ZooKeeper not available");
271 } catch (IOException e
) {
272 LOG
.error("Got IOException: " +e
.getMessage(), e
);
278 private void waitOnMasterThreads(LocalHBaseCluster cluster
) throws InterruptedException
{
279 List
<JVMClusterUtil
.MasterThread
> masters
= cluster
.getMasters();
280 List
<JVMClusterUtil
.RegionServerThread
> regionservers
= cluster
.getRegionServers();
282 if (masters
!= null) {
283 for (JVMClusterUtil
.MasterThread t
: masters
) {
285 if(t
.getMaster().isAborted()) {
286 closeAllRegionServerThreads(regionservers
);
287 throw new RuntimeException("HMaster Aborted");
293 private static void closeAllRegionServerThreads(
294 List
<JVMClusterUtil
.RegionServerThread
> regionservers
) {
295 for(JVMClusterUtil
.RegionServerThread t
: regionservers
){
296 t
.getRegionServer().stop("HMaster Aborted; Bringing down regions servers");
301 * Version of master that will shutdown the passed zk cluster on its way out.
303 public static class LocalHMaster
extends HMaster
{
304 private MiniZooKeeperCluster zkcluster
= null;
306 public LocalHMaster(Configuration conf
)
307 throws IOException
, KeeperException
, InterruptedException
{
314 if (this.zkcluster
!= null) {
316 this.zkcluster
.shutdown();
317 } catch (IOException e
) {
318 LOG
.error("Failed to shutdown MiniZooKeeperCluster", e
);
323 void setZKCluster(final MiniZooKeeperCluster zkcluster
) {
324 this.zkcluster
= zkcluster
;