1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
43
44
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
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
88
89
90 void doMain(final String[] args) throws Exception {
91 processOptions(args);
92
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
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
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
151
152
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
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
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
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
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
232
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 }