View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase.thrift;
20  
21  import java.util.Arrays;
22  import java.util.List;
23  
24  import org.apache.commons.cli.CommandLine;
25  import org.apache.commons.cli.CommandLineParser;
26  import org.apache.commons.cli.HelpFormatter;
27  import org.apache.commons.cli.Options;
28  import org.apache.commons.cli.PosixParser;
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.apache.hadoop.conf.Configuration;
32  import org.apache.hadoop.hbase.HBaseConfiguration;
33  import org.apache.hadoop.hbase.security.User;
34  import org.apache.hadoop.hbase.thrift.ThriftServerRunner.ImplType;
35  import org.apache.hadoop.hbase.util.InfoServer;
36  import org.apache.hadoop.hbase.util.Strings;
37  import org.apache.hadoop.hbase.util.VersionInfo;
38  import org.apache.hadoop.net.DNS;
39  import org.apache.hadoop.util.Shell.ExitCodeException;
40  
41  /**
42   * ThriftServer- this class starts up a Thrift server which implements the
43   * Hbase API specified in the Hbase.thrift IDL file. The server runs in an
44   * independent process.
45   */
46  public class ThriftServer {
47  
48    private static final Log LOG = LogFactory.getLog(ThriftServer.class);
49  
50    private static final String MIN_WORKERS_OPTION = "minWorkers";
51    private static final String MAX_WORKERS_OPTION = "workers";
52    private static final String MAX_QUEUE_SIZE_OPTION = "queue";
53    private static final String KEEP_ALIVE_SEC_OPTION = "keepAliveSec";
54    static final String BIND_OPTION = "bind";
55    static final String COMPACT_OPTION = "compact";
56    static final String FRAMED_OPTION = "framed";
57    static final String PORT_OPTION = "port";
58  
59    private static final String DEFAULT_BIND_ADDR = "0.0.0.0";
60    private static final int DEFAULT_LISTEN_PORT = 9090;
61  
62    private Configuration conf;
63    ThriftServerRunner serverRunner;
64  
65    private InfoServer infoServer;
66  
67    //
68    // Main program and support routines
69    //
70  
71    public ThriftServer(Configuration conf) {
72      this.conf = HBaseConfiguration.create(conf);
73    }
74  
75    private static void printUsageAndExit(Options options, int exitCode)
76        throws ExitCodeException {
77      HelpFormatter formatter = new HelpFormatter();
78      formatter.printHelp("Thrift", null, options,
79          "To start the Thrift server run 'bin/hbase-daemon.sh start thrift'\n" +
80          "To shutdown the thrift server run 'bin/hbase-daemon.sh stop " +
81          "thrift' or send a kill signal to the thrift server pid",
82          true);
83      throw new ExitCodeException(exitCode, "");
84    }
85  
86    /**
87     * Start up or shuts down the Thrift server, depending on the arguments.
88     * @param args
89     */
90     void doMain(final String[] args) throws Exception {
91       processOptions(args);
92       // login the server principal (if using secure Hadoop)
93       if (User.isSecurityEnabled() && User.isHBaseSecurityEnabled(conf)) {
94         String machineName = Strings.domainNamePointerToHostName(
95           DNS.getDefaultHost(conf.get("hbase.thrift.dns.interface", "default"),
96             conf.get("hbase.thrift.dns.nameserver", "default")));
97         User.login(conf, "hbase.thrift.keytab.file",
98             "hbase.thrift.kerberos.principal", machineName);
99       }
100      serverRunner = new ThriftServerRunner(conf);
101 
102      // Put up info server.
103      int port = conf.getInt("hbase.thrift.info.port", 9095);
104      if (port >= 0) {
105        conf.setLong("startcode", System.currentTimeMillis());
106        String a = conf.get("hbase.thrift.info.bindAddress", "0.0.0.0");
107        infoServer = new InfoServer("thrift", a, port, false, conf);
108        infoServer.setAttribute("hbase.conf", conf);
109        infoServer.start();
110      }
111      serverRunner.run();
112   }
113 
114   /**
115    * Parse the command line options to set parameters the conf.
116    */
117   private void processOptions(final String[] args) throws Exception {
118     Options options = new Options();
119     options.addOption("b", BIND_OPTION, true, "Address to bind " +
120         "the Thrift server to. Not supported by the Nonblocking and " +
121         "HsHa server [default: " + DEFAULT_BIND_ADDR + "]");
122     options.addOption("p", PORT_OPTION, true, "Port to bind to [default: " +
123         DEFAULT_LISTEN_PORT + "]");
124     options.addOption("f", FRAMED_OPTION, false, "Use framed transport");
125     options.addOption("c", COMPACT_OPTION, false, "Use the compact protocol");
126     options.addOption("h", "help", false, "Print help information");
127     options.addOption(null, "infoport", true, "Port for web UI");
128 
129     options.addOption("m", MIN_WORKERS_OPTION, true,
130         "The minimum number of worker threads for " +
131         ImplType.THREAD_POOL.simpleClassName());
132 
133     options.addOption("w", MAX_WORKERS_OPTION, true,
134         "The maximum number of worker threads for " +
135         ImplType.THREAD_POOL.simpleClassName());
136 
137     options.addOption("q", MAX_QUEUE_SIZE_OPTION, true,
138         "The maximum number of queued requests in " +
139         ImplType.THREAD_POOL.simpleClassName());
140 
141     options.addOption("k", KEEP_ALIVE_SEC_OPTION, true,
142         "The amount of time in secods to keep a thread alive when idle in " +
143         ImplType.THREAD_POOL.simpleClassName());
144 
145     options.addOptionGroup(ImplType.createOptionGroup());
146 
147     CommandLineParser parser = new PosixParser();
148     CommandLine cmd = parser.parse(options, args);
149 
150     // This is so complicated to please both bin/hbase and bin/hbase-daemon.
151     // hbase-daemon provides "start" and "stop" arguments
152     // hbase should print the help if no argument is provided
153     List<String> commandLine = Arrays.asList(args);
154     boolean stop = commandLine.contains("stop");
155     boolean start = commandLine.contains("start");
156     boolean invalidStartStop = (start && stop) || (!start && !stop);
157     if (cmd.hasOption("help") || invalidStartStop) {
158       if (invalidStartStop) {
159         LOG.error("Exactly one of 'start' and 'stop' has to be specified");
160       }
161       printUsageAndExit(options, 1);
162     }
163 
164     // Get port to bind to
165     try {
166       int listenPort = Integer.parseInt(cmd.getOptionValue(PORT_OPTION,
167           String.valueOf(DEFAULT_LISTEN_PORT)));
168       conf.setInt(ThriftServerRunner.PORT_CONF_KEY, listenPort);
169     } catch (NumberFormatException e) {
170       LOG.error("Could not parse the value provided for the port option", e);
171       printUsageAndExit(options, -1);
172     }
173 
174     // check for user-defined info server port setting, if so override the conf
175     try {
176       if (cmd.hasOption("infoport")) {
177         String val = cmd.getOptionValue("infoport");
178         conf.setInt("hbase.thrift.info.port", Integer.valueOf(val));
179         LOG.debug("Web UI port set to " + val);
180       }
181     } catch (NumberFormatException e) {
182       LOG.error("Could not parse the value provided for the infoport option", e);
183       printUsageAndExit(options, -1);
184     }
185 
186     // Make optional changes to the configuration based on command-line options
187     optionToConf(cmd, MIN_WORKERS_OPTION,
188         conf, TBoundedThreadPoolServer.MIN_WORKER_THREADS_CONF_KEY);
189     optionToConf(cmd, MAX_WORKERS_OPTION,
190         conf, TBoundedThreadPoolServer.MAX_WORKER_THREADS_CONF_KEY);
191     optionToConf(cmd, MAX_QUEUE_SIZE_OPTION,
192         conf, TBoundedThreadPoolServer.MAX_QUEUED_REQUESTS_CONF_KEY);
193     optionToConf(cmd, KEEP_ALIVE_SEC_OPTION,
194         conf, TBoundedThreadPoolServer.THREAD_KEEP_ALIVE_TIME_SEC_CONF_KEY);
195 
196     // Set general thrift server options
197     conf.setBoolean(
198         ThriftServerRunner.COMPACT_CONF_KEY, cmd.hasOption(COMPACT_OPTION));
199     conf.setBoolean(
200         ThriftServerRunner.FRAMED_CONF_KEY, cmd.hasOption(FRAMED_OPTION));
201     if (cmd.hasOption(BIND_OPTION)) {
202       conf.set(
203           ThriftServerRunner.BIND_CONF_KEY, cmd.getOptionValue(BIND_OPTION));
204     }
205 
206     ImplType.setServerImpl(cmd, conf);
207   }
208 
209   public void stop() {
210     if (this.infoServer != null) {
211       LOG.info("Stopping infoServer");
212       try {
213         this.infoServer.stop();
214       } catch (Exception ex) {
215         ex.printStackTrace();
216       }
217     }
218     serverRunner.shutdown();
219   }
220 
221   private static void optionToConf(CommandLine cmd, String option,
222       Configuration conf, String destConfKey) {
223     if (cmd.hasOption(option)) {
224       String value = cmd.getOptionValue(option);
225       LOG.info("Set configuration key:" + destConfKey + " value:" + value);
226       conf.set(destConfKey, value);
227     }
228   }
229 
230   /**
231    * @param args
232    * @throws Exception
233    */
234   public static void main(String [] args) throws Exception {
235     VersionInfo.logVersion();
236     try {
237       new ThriftServer(HBaseConfiguration.create()).doMain(args);
238     } catch (ExitCodeException ex) {
239       System.exit(ex.getExitCode());
240     }
241   }
242 }