in zuul-core/src/main/java/com/netflix/zuul/netty/server/ClientConnectionsShutdown.java [102:149]
Promise<Void> gracefullyShutdownClientChannels(ShutdownType shutdownType) {
// Mark all active connections to be closed after next response sent.
LOG.warn("Flagging CLOSE_AFTER_RESPONSE on {} client channels.", channels.size());
// racy situation if new connections are still coming in, but any channels created after newCloseFuture will
// be closed during the force close stage
ChannelGroupFuture closeFuture = channels.newCloseFuture();
for (Channel channel : channels) {
flagChannelForClose(channel, shutdownType);
}
LOG.info("Setting up scheduled task for {} with shutdownType: {}", closeFuture, shutdownType);
Promise<Void> promise = executor.newPromise();
Runnable cancelTimeoutTask;
if (shutdownType == ShutdownType.SHUTDOWN) {
ScheduledFuture<?> timeoutTask = executor.schedule(
() -> {
LOG.warn("Force closing remaining {} active client channels.", channels.size());
channels.close().addListener(future -> {
if (!future.isSuccess()) {
LOG.error("Failed to close all connections", future.cause());
}
if (!promise.isDone()) {
promise.setSuccess(null);
}
});
},
GRACEFUL_CLOSE_TIMEOUT.get(),
TimeUnit.SECONDS);
cancelTimeoutTask = () -> {
if (!timeoutTask.isDone()) {
LOG.info("Timeout task canceled before completion.");
// close happened before the timeout
timeoutTask.cancel(false);
}
};
} else {
cancelTimeoutTask = () -> {};
}
closeFuture.addListener(future -> {
LOG.info("CloseFuture completed successfully: {}", future.isSuccess());
cancelTimeoutTask.run();
promise.setSuccess(null);
});
return promise;
}