|
31 | 31 |
|
32 | 32 | package com.google.net.stubby.testing.integration; |
33 | 33 |
|
34 | | -import com.google.common.base.Preconditions; |
35 | | -import com.google.common.collect.Maps; |
36 | 34 | import com.google.common.util.concurrent.MoreExecutors; |
37 | 35 | import com.google.net.stubby.ServerImpl; |
38 | 36 | import com.google.net.stubby.ServerInterceptors; |
|
42 | 40 | import io.netty.handler.ssl.SslContext; |
43 | 41 |
|
44 | 42 | import java.io.File; |
45 | | -import java.util.Map; |
46 | 43 | import java.util.concurrent.Executors; |
47 | 44 | import java.util.concurrent.ScheduledExecutorService; |
48 | 45 | import java.util.concurrent.TimeUnit; |
49 | | -import java.util.logging.Logger; |
50 | 46 |
|
51 | 47 | /** |
52 | | - * Server that manages startup/shutdown of a single {@code TestService}. The server can be started |
53 | | - * with any one of the supported transports. |
| 48 | + * Server that manages startup/shutdown of a single {@code TestService}. |
54 | 49 | */ |
55 | 50 | public class TestServiceServer { |
56 | | - private static final int DEFAULT_NUM_THREADS = 100; |
57 | | - private static final int STARTUP_TIMEOUT_MILLS = 5000; |
58 | | - private static final String RPC_PORT_ARG = "--port"; |
59 | | - private static final String TRANSPORT_ARG = "--transport"; |
60 | | - private static final String GRPC_VERSION_ARG = "--grpc_version"; |
61 | | - private final TestServiceImpl testService; |
62 | | - |
63 | | - /** Supported transport protocols */ |
64 | | - public enum Transport { |
65 | | - HTTP2_NETTY, HTTP2_NETTY_TLS |
66 | | - } |
67 | | - |
68 | | - private static final Logger log = Logger.getLogger(TestServiceServer.class.getName()); |
69 | | - |
70 | | - private final ScheduledExecutorService executor; |
71 | | - private final int port; |
72 | | - private final ServerImpl server; |
73 | | - |
74 | | - /** |
75 | | - * Constructs the GRPC server. |
76 | | - * |
77 | | - * @param transport the transport over which to send GRPC frames. |
78 | | - * @param port the port to be used for RPC communications. |
79 | | - */ |
80 | | - public TestServiceServer(Transport transport, int port) |
81 | | - throws Exception { |
82 | | - Preconditions.checkNotNull(transport, "transport"); |
83 | | - this.executor = Executors.newScheduledThreadPool(DEFAULT_NUM_THREADS); |
84 | | - this.port = port; |
85 | | - |
86 | | - // Create the GRPC service. |
87 | | - testService = new TestServiceImpl(executor); |
88 | | - |
89 | | - switch (transport) { |
90 | | - case HTTP2_NETTY: |
91 | | - server = createServer(false); |
92 | | - break; |
93 | | - case HTTP2_NETTY_TLS: |
94 | | - server = createServer(true); |
95 | | - break; |
96 | | - default: |
97 | | - throw new IllegalArgumentException("Unsupported transport: " + transport); |
98 | | - } |
99 | | - } |
100 | | - |
101 | | - public void start() throws Exception { |
102 | | - server.startAsync(); |
103 | | - server.awaitRunning(STARTUP_TIMEOUT_MILLS, TimeUnit.MILLISECONDS); |
104 | | - log.info("GRPC server started."); |
105 | | - } |
106 | | - |
107 | | - public void stop() throws Exception { |
108 | | - log.info("GRPC server stopping..."); |
109 | | - server.stopAsync(); |
110 | | - server.awaitTerminated(); |
111 | | - MoreExecutors.shutdownAndAwaitTermination(executor, 5, TimeUnit.SECONDS); |
112 | | - } |
113 | | - |
114 | 51 | /** |
115 | | - * The main application allowing this server to be launched from the command line. Accepts the |
116 | | - * following arguments: |
117 | | - * <p> |
118 | | - * --transport=<HTTP2_NETTY|HTTP2_NETTY_TLS> Identifies the transport |
119 | | - * over which GRPC frames should be sent. <br> |
120 | | - * --port=<port number> The port number for RPC communications. |
| 52 | + * The main application allowing this server to be launched from the command line. |
121 | 53 | */ |
122 | 54 | public static void main(String[] args) throws Exception { |
123 | | - Map<String, String> argMap = parseArgs(args); |
124 | | - Transport transport = getTransport(argMap); |
125 | | - int port = getPort(RPC_PORT_ARG, argMap); |
126 | | - |
127 | | - // TODO(user): Remove. Ideally stop passing the arg in scripts first. |
128 | | - if (getGrpcVersion(argMap) != 2) { |
129 | | - System.err.println("Only grpc_version=2 is supported"); |
130 | | - System.exit(1); |
131 | | - } |
132 | | - |
133 | | - final TestServiceServer server = new TestServiceServer(transport, port); |
| 55 | + final TestServiceServer server = new TestServiceServer(); |
| 56 | + server.parseArgs(args); |
134 | 57 |
|
135 | 58 | Runtime.getRuntime().addShutdownHook(new Thread() { |
136 | 59 | @Override |
137 | 60 | public void run() { |
138 | 61 | try { |
| 62 | + System.out.println("Shutting down"); |
139 | 63 | server.stop(); |
140 | 64 | } catch (Exception e) { |
141 | 65 | e.printStackTrace(); |
142 | 66 | } |
143 | 67 | } |
144 | 68 | }); |
145 | 69 | server.start(); |
| 70 | + System.out.println("Server started"); |
146 | 71 | } |
147 | 72 |
|
148 | | - private static Transport getTransport(Map<String, String> argMap) { |
149 | | - String value = argMap.get(TRANSPORT_ARG.toLowerCase()); |
150 | | - Preconditions.checkNotNull(value, "%s argument must be provided.", TRANSPORT_ARG); |
151 | | - Transport transport = Transport.valueOf(value.toUpperCase().trim()); |
152 | | - System.out.println(TRANSPORT_ARG + " set to: " + transport); |
153 | | - return transport; |
154 | | - } |
155 | | - |
156 | | - private static int getPort(String argName, Map<String, String> argMap) { |
157 | | - String value = argMap.get(argName.toLowerCase()); |
158 | | - if (value != null) { |
159 | | - int port = Integer.parseInt(value); |
160 | | - System.out.println(argName + " set to port: " + port); |
161 | | - return port; |
162 | | - } |
| 73 | + private int port = 8080; |
| 74 | + private boolean useTls = true; |
163 | 75 |
|
164 | | - int port = Util.pickUnusedPort(); |
165 | | - System.out.println(argName + " not, provided. Using port: " + port); |
166 | | - return port; |
167 | | - } |
168 | | - |
169 | | - private static int getGrpcVersion(Map<String, String> argMap) { |
170 | | - String value = argMap.get(GRPC_VERSION_ARG.toLowerCase()); |
171 | | - if (value == null) { |
172 | | - return 2; |
173 | | - } |
174 | | - int version = Integer.parseInt(value); |
175 | | - System.out.println(GRPC_VERSION_ARG + " set to version: " + version); |
176 | | - return version; |
177 | | - } |
| 76 | + private ScheduledExecutorService executor; |
| 77 | + private ServerImpl server; |
178 | 78 |
|
179 | | - private static Map<String, String> parseArgs(String[] args) { |
180 | | - Map<String, String> argMap = Maps.newHashMap(); |
| 79 | + private void parseArgs(String[] args) { |
| 80 | + boolean usage = false; |
181 | 81 | for (String arg : args) { |
182 | | - String[] parts = arg.split("="); |
183 | | - Preconditions.checkArgument(parts.length == 2, "Failed parsing argument: %s", arg); |
184 | | - argMap.put(parts[0].toLowerCase().trim(), parts[1].trim()); |
| 82 | + if (!arg.startsWith("--")) { |
| 83 | + System.err.println("All arguments must start with '--': " + arg); |
| 84 | + usage = true; |
| 85 | + break; |
| 86 | + } |
| 87 | + String[] parts = arg.substring(2).split("=", 2); |
| 88 | + String key = parts[0]; |
| 89 | + if ("help".equals(key)) { |
| 90 | + usage = true; |
| 91 | + break; |
| 92 | + } |
| 93 | + if (parts.length != 2) { |
| 94 | + System.err.println("All arguments must be of the form --arg=value"); |
| 95 | + usage = true; |
| 96 | + break; |
| 97 | + } |
| 98 | + String value = parts[1]; |
| 99 | + if ("port".equals(key)) { |
| 100 | + port = Integer.parseInt(value); |
| 101 | + } else if ("use_tls".equals(key)) { |
| 102 | + useTls = Boolean.parseBoolean(value); |
| 103 | + } else if ("grpc_version".equals(key)) { |
| 104 | + if (!"2".equals(value)) { |
| 105 | + System.err.println("Only grpc version 2 is supported"); |
| 106 | + usage = true; |
| 107 | + break; |
| 108 | + } |
| 109 | + } else { |
| 110 | + System.err.println("Unknown argument: " + key); |
| 111 | + usage = true; |
| 112 | + break; |
| 113 | + } |
| 114 | + } |
| 115 | + if (usage) { |
| 116 | + TestServiceServer s = new TestServiceServer(); |
| 117 | + System.out.println( |
| 118 | + "Usage: [ARGS...]" |
| 119 | + + "\n" |
| 120 | + + "\n --port=PORT Port to connect to. Default " + s.port |
| 121 | + + "\n --use_tls=true|false Whether to use TLS. Default " + s.useTls |
| 122 | + ); |
| 123 | + System.exit(1); |
185 | 124 | } |
186 | | - |
187 | | - return argMap; |
188 | 125 | } |
189 | 126 |
|
190 | | - private ServerImpl createServer(boolean enableSSL) throws Exception { |
| 127 | + private void start() throws Exception { |
| 128 | + executor = Executors.newSingleThreadScheduledExecutor(); |
191 | 129 | SslContext sslContext = null; |
192 | | - if (enableSSL) { |
| 130 | + if (useTls) { |
193 | 131 | String dir = "integration-testing/certs"; |
194 | 132 | sslContext = SslContext.newServerContext( |
195 | 133 | new File(dir + "/server1.pem"), |
196 | 134 | new File(dir + "/server1.key")); |
197 | 135 | } |
198 | | - return NettyServerBuilder.forPort(port) |
199 | | - .executor(executor) |
| 136 | + server = NettyServerBuilder.forPort(port) |
200 | 137 | .sslContext(sslContext) |
201 | | - .addService(ServerInterceptors.intercept(TestServiceGrpc.bindService(testService), |
202 | | - TestUtils.echoRequestHeadersInterceptor(Util.METADATA_KEY))) |
| 138 | + .addService(ServerInterceptors.intercept( |
| 139 | + TestServiceGrpc.bindService(new TestServiceImpl(executor)), |
| 140 | + TestUtils.echoRequestHeadersInterceptor(Util.METADATA_KEY))) |
203 | 141 | .build(); |
| 142 | + server.startAsync(); |
| 143 | + server.awaitRunning(5, TimeUnit.SECONDS); |
| 144 | + } |
| 145 | + |
| 146 | + private void stop() throws Exception { |
| 147 | + server.stopAsync(); |
| 148 | + server.awaitTerminated(); |
| 149 | + MoreExecutors.shutdownAndAwaitTermination(executor, 5, TimeUnit.SECONDS); |
204 | 150 | } |
205 | 151 | } |
0 commit comments