Changing TestServiceServer to use ListenableFuture for determining when the server has been successfully started.

Previously, it was creating a client socket to determine when the server
was bound to the port. This causes the Netty server to create and then
quickly fail a client channel which was generating noisy error logs.
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=80546045
This commit is contained in:
nathanmittler 2014-11-22 09:54:18 -08:00 committed by Eric Anderson
parent be29ba57cc
commit abdbf4940a
2 changed files with 20 additions and 86 deletions

View File

@ -11,8 +11,6 @@ import com.google.net.stubby.transport.netty.NettyServerBuilder;
import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContext;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.net.Socket;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
@ -40,7 +38,7 @@ public class TestServiceServer {
private final ScheduledExecutorService executor; private final ScheduledExecutorService executor;
private final int port; private final int port;
private final ServerController serverController; private final ServerImpl server;
/** /**
* Constructs the GRPC server. * Constructs the GRPC server.
@ -59,10 +57,10 @@ public class TestServiceServer {
switch (transport) { switch (transport) {
case HTTP2_NETTY: case HTTP2_NETTY:
serverController = new Http2NettyController(false); server = createServer(false);
break; break;
case HTTP2_NETTY_TLS: case HTTP2_NETTY_TLS:
serverController = new Http2NettyController(true); server = createServer(true);
break; break;
default: default:
throw new IllegalArgumentException("Unsupported transport: " + transport); throw new IllegalArgumentException("Unsupported transport: " + transport);
@ -70,14 +68,15 @@ public class TestServiceServer {
} }
public void start() throws Exception { public void start() throws Exception {
serverController.start(); server.startAsync();
assertStart(); server.awaitRunning(STARTUP_TIMEOUT_MILLS, TimeUnit.MILLISECONDS);
log.info("GRPC server started."); log.info("GRPC server started.");
} }
public void stop() throws Exception { public void stop() throws Exception {
log.info("GRPC server stopping..."); log.info("GRPC server stopping...");
serverController.stop(); server.stopAsync();
server.awaitTerminated();
MoreExecutors.shutdownAndAwaitTermination(executor, 5, TimeUnit.SECONDS); MoreExecutors.shutdownAndAwaitTermination(executor, 5, TimeUnit.SECONDS);
} }
@ -155,24 +154,7 @@ public class TestServiceServer {
return argMap; return argMap;
} }
/** private ServerImpl createServer(boolean enableSSL) throws Exception {
* A simple interface for an object controlling the lifecycle of the underlying server
* implementation.
*/
private interface ServerController {
void start() throws Exception;
void stop() throws Exception;
}
/**
* A controller for a Netty-based Http2 server.
*/
private class Http2NettyController implements ServerController {
private final ServerImpl server;
public Http2NettyController(boolean enableSSL) throws Exception {
SslContext sslContext = null; SslContext sslContext = null;
if (enableSSL) { if (enableSSL) {
String dir = "integration-testing/certs"; String dir = "integration-testing/certs";
@ -180,59 +162,11 @@ public class TestServiceServer {
new File(dir + "/server1.pem"), new File(dir + "/server1.pem"),
new File(dir + "/server1.key")); new File(dir + "/server1.key"));
} }
server = NettyServerBuilder.forPort(port) return NettyServerBuilder.forPort(port)
.executor(executor) .executor(executor)
.sslContext(sslContext) .sslContext(sslContext)
.addService(ServerInterceptors.intercept(TestServiceGrpc.bindService(testService), .addService(ServerInterceptors.intercept(TestServiceGrpc.bindService(testService),
TestUtils.echoRequestHeadersInterceptor(Util.METADATA_KEY))) TestUtils.echoRequestHeadersInterceptor(Util.METADATA_KEY)))
.build(); .build();
} }
@Override
public void start() throws Exception {
executor.execute(new Runnable() {
@Override
public void run() {
server.startAsync();
server.awaitRunning();
}
});
}
@Override
public void stop() throws Exception {
server.stopAsync();
server.awaitTerminated();
}
}
// Asserts that the server has started listening.
private void assertStart() throws Exception {
long endTimeMillis = System.currentTimeMillis() + STARTUP_TIMEOUT_MILLS;
boolean timedOut = false;
while (!serverListening("localhost", port)) {
if (System.currentTimeMillis() > endTimeMillis) {
timedOut = true;
break;
}
}
if (timedOut) {
throw new RuntimeException("Failed to start server.");
}
log.info("Server is listening on port: " + port);
}
private boolean serverListening(String host, int port) {
Socket socket = null;
try {
socket = new Socket(host, port);
return true;
} catch (IOException e) {
return false;
} finally {
if (socket != null) {
try { socket.close(); } catch (IOException expected) {}
}
}
}
} }

Binary file not shown.