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.classification.InterfaceAudience;
32 import org.apache.hadoop.conf.Configuration;
33 import org.apache.hadoop.hbase.HBaseConfiguration;
34 import org.apache.hadoop.hbase.security.User;
35 import org.apache.hadoop.hbase.security.UserProvider;
36 import org.apache.hadoop.hbase.thrift.ThriftServerRunner.ImplType;
37 import org.apache.hadoop.hbase.util.InfoServer;
38 import org.apache.hadoop.hbase.util.Strings;
39 import org.apache.hadoop.hbase.util.VersionInfo;
40 import org.apache.hadoop.net.DNS;
41 import org.apache.hadoop.util.Shell.ExitCodeException;
42
43
44
45
46
47
48 @InterfaceAudience.Private
49 public class ThriftServer {
50
51 private static final Log LOG = LogFactory.getLog(ThriftServer.class);
52
53 private static final String MIN_WORKERS_OPTION = "minWorkers";
54 private static final String MAX_WORKERS_OPTION = "workers";
55 private static final String MAX_QUEUE_SIZE_OPTION = "queue";
56 private static final String KEEP_ALIVE_SEC_OPTION = "keepAliveSec";
57 static final String BIND_OPTION = "bind";
58 static final String COMPACT_OPTION = "compact";
59 static final String FRAMED_OPTION = "framed";
60 static final String PORT_OPTION = "port";
61
62 private static final String DEFAULT_BIND_ADDR = "0.0.0.0";
63 private static final int DEFAULT_LISTEN_PORT = 9090;
64
65 private Configuration conf;
66 ThriftServerRunner serverRunner;
67
68 private InfoServer infoServer;
69
70
71
72
73
74 public ThriftServer(Configuration conf) {
75 this.conf = HBaseConfiguration.create(conf);
76 }
77
78 private static void printUsageAndExit(Options options, int exitCode)
79 throws ExitCodeException {
80 HelpFormatter formatter = new HelpFormatter();
81 formatter.printHelp("Thrift", null, options,
82 "To start the Thrift server run 'bin/hbase-daemon.sh start thrift'\n" +
83 "To shutdown the thrift server run 'bin/hbase-daemon.sh stop " +
84 "thrift' or send a kill signal to the thrift server pid",
85 true);
86 throw new ExitCodeException(exitCode, "");
87 }
88
89
90
91
92
93 void doMain(final String[] args) throws Exception {
94 processOptions(args);
95
96 UserProvider userProvider = UserProvider.instantiate(conf);
97
98 if (userProvider.isHadoopSecurityEnabled() && userProvider.isHBaseSecurityEnabled()) {
99 String machineName =
100 Strings.domainNamePointerToHostName(DNS.getDefaultHost(
101 conf.get("hbase.thrift.dns.interface", "default"),
102 conf.get("hbase.thrift.dns.nameserver", "default")));
103 userProvider
104 .login("hbase.thrift.keytab.file", "hbase.thrift.kerberos.principal", machineName);
105 }
106
107 serverRunner = new ThriftServerRunner(conf);
108
109
110 int port = conf.getInt("hbase.thrift.info.port", 9095);
111 if (port >= 0) {
112 conf.setLong("startcode", System.currentTimeMillis());
113 String a = conf.get("hbase.thrift.info.bindAddress", "0.0.0.0");
114 infoServer = new InfoServer("thrift", a, port, false, conf);
115 infoServer.setAttribute("hbase.conf", conf);
116 infoServer.start();
117 }
118 serverRunner.run();
119 }
120
121
122
123
124 private void processOptions(final String[] args) throws Exception {
125 Options options = new Options();
126 options.addOption("b", BIND_OPTION, true, "Address to bind " +
127 "the Thrift server to. [default: " + DEFAULT_BIND_ADDR + "]");
128 options.addOption("p", PORT_OPTION, true, "Port to bind to [default: " +
129 DEFAULT_LISTEN_PORT + "]");
130 options.addOption("f", FRAMED_OPTION, false, "Use framed transport");
131 options.addOption("c", COMPACT_OPTION, false, "Use the compact protocol");
132 options.addOption("h", "help", false, "Print help information");
133 options.addOption(null, "infoport", true, "Port for web UI");
134
135 options.addOption("m", MIN_WORKERS_OPTION, true,
136 "The minimum number of worker threads for " +
137 ImplType.THREAD_POOL.simpleClassName());
138
139 options.addOption("w", MAX_WORKERS_OPTION, true,
140 "The maximum number of worker threads for " +
141 ImplType.THREAD_POOL.simpleClassName());
142
143 options.addOption("q", MAX_QUEUE_SIZE_OPTION, true,
144 "The maximum number of queued requests in " +
145 ImplType.THREAD_POOL.simpleClassName());
146
147 options.addOption("k", KEEP_ALIVE_SEC_OPTION, true,
148 "The amount of time in secods to keep a thread alive when idle in " +
149 ImplType.THREAD_POOL.simpleClassName());
150
151 options.addOptionGroup(ImplType.createOptionGroup());
152
153 CommandLineParser parser = new PosixParser();
154 CommandLine cmd = parser.parse(options, args);
155
156
157
158
159 List<String> commandLine = Arrays.asList(args);
160 boolean stop = commandLine.contains("stop");
161 boolean start = commandLine.contains("start");
162 boolean invalidStartStop = (start && stop) || (!start && !stop);
163 if (cmd.hasOption("help") || invalidStartStop) {
164 if (invalidStartStop) {
165 LOG.error("Exactly one of 'start' and 'stop' has to be specified");
166 }
167 printUsageAndExit(options, 1);
168 }
169
170
171 try {
172 int listenPort = Integer.parseInt(cmd.getOptionValue(PORT_OPTION,
173 String.valueOf(DEFAULT_LISTEN_PORT)));
174 conf.setInt(ThriftServerRunner.PORT_CONF_KEY, listenPort);
175 } catch (NumberFormatException e) {
176 LOG.error("Could not parse the value provided for the port option", e);
177 printUsageAndExit(options, -1);
178 }
179
180
181 try {
182 if (cmd.hasOption("infoport")) {
183 String val = cmd.getOptionValue("infoport");
184 conf.setInt("hbase.thrift.info.port", Integer.valueOf(val));
185 LOG.debug("Web UI port set to " + val);
186 }
187 } catch (NumberFormatException e) {
188 LOG.error("Could not parse the value provided for the infoport option", e);
189 printUsageAndExit(options, -1);
190 }
191
192
193 optionToConf(cmd, MIN_WORKERS_OPTION,
194 conf, TBoundedThreadPoolServer.MIN_WORKER_THREADS_CONF_KEY);
195 optionToConf(cmd, MAX_WORKERS_OPTION,
196 conf, TBoundedThreadPoolServer.MAX_WORKER_THREADS_CONF_KEY);
197 optionToConf(cmd, MAX_QUEUE_SIZE_OPTION,
198 conf, TBoundedThreadPoolServer.MAX_QUEUED_REQUESTS_CONF_KEY);
199 optionToConf(cmd, KEEP_ALIVE_SEC_OPTION,
200 conf, TBoundedThreadPoolServer.THREAD_KEEP_ALIVE_TIME_SEC_CONF_KEY);
201
202
203 boolean compact = cmd.hasOption(COMPACT_OPTION) ||
204 conf.getBoolean(ThriftServerRunner.COMPACT_CONF_KEY, false);
205 conf.setBoolean(ThriftServerRunner.COMPACT_CONF_KEY, compact);
206 boolean framed = cmd.hasOption(FRAMED_OPTION) ||
207 conf.getBoolean(ThriftServerRunner.FRAMED_CONF_KEY, false);
208 conf.setBoolean(ThriftServerRunner.FRAMED_CONF_KEY, framed);
209 if (cmd.hasOption(BIND_OPTION)) {
210 conf.set(
211 ThriftServerRunner.BIND_CONF_KEY, cmd.getOptionValue(BIND_OPTION));
212 }
213
214 ImplType.setServerImpl(cmd, conf);
215 }
216
217 public void stop() {
218 if (this.infoServer != null) {
219 LOG.info("Stopping infoServer");
220 try {
221 this.infoServer.stop();
222 } catch (Exception ex) {
223 ex.printStackTrace();
224 }
225 }
226 serverRunner.shutdown();
227 }
228
229 private static void optionToConf(CommandLine cmd, String option,
230 Configuration conf, String destConfKey) {
231 if (cmd.hasOption(option)) {
232 String value = cmd.getOptionValue(option);
233 LOG.info("Set configuration key:" + destConfKey + " value:" + value);
234 conf.set(destConfKey, value);
235 }
236 }
237
238
239
240
241
242 public static void main(String [] args) throws Exception {
243 VersionInfo.logVersion();
244 try {
245 new ThriftServer(HBaseConfiguration.create()).doMain(args);
246 } catch (ExitCodeException ex) {
247 System.exit(ex.getExitCode());
248 }
249 }
250 }