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