Skip to content

Conversation

@dapengzhang0
Copy link
Contributor

resolves #3442

decoder().flowController().initialWindowSize(connection().connectionStream())));
}
} else if (data == MAX_CONNECTION_AGE_PING) {
checkNotNull(maxAgeShutdownRunner, "maxAgeShutdownRunner");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not throw a normal runtime exception in response to something received (we could throw a Http2Exception though). Logging a warning would be fine though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will never throw a RuntimeException unless there's a bug in the code. If there's a bug in the code, it will throw NPE anyway even if checkNotNull is not there. The checkNotNull here is just an assert without -ea flag. checkNotNull and assert can help find a bug, but logging a warning may not be that helpful. There are checkNotNull even in the constructors of Http2Exception.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then make it an assert or manually throw new AssertionError(). checkNotNull is best used when verifying your input, and telling the caller they made a mistake.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@CheckForNull
private GracefulShutdownRunner maxAgeShutdownRunner;
@CheckForNull
private GracefulShutdownRunner maxIdleShutdownRunner;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use two separate flows for the two different causes for shutdown. It doesn't matter why we are shutting down. If we're already shutting down and we want to shutdown again, then do nothing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


private final class GracefulShutdownRunner {

ChannelHandlerContext ctx;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see no reason to save ctx here. Pass it in explicitly to each method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

private final class GracefulShutdownRunner {

ChannelHandlerContext ctx;
long payload;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the same id for all cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}
}

private final class GracefulShutdownRunner {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this a "runner"? It seems like run is just being used as a generic "do" method. Instead, give it a better name, like start (because it won't actually finish when it returns) or sendGoAway.

Even more though, I think the run() shouldn't be on this class. Instead, make a method directly in NettyServerHandler like gracefulShutdown or startGracefulShutdown. It would issue the initial GOAWAY and save state (this class) for later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed Runner in name. Renamed run() by start().

Http2Error.NO_ERROR.code(),
ByteBufUtil.writeAscii(ctx.alloc(), goAwayMessage),
ctx.newPromise());
ctx.flush();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This flush is unnecessary. Another is following it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

TimeUnit.NANOSECONDS);

encoder().writePing(ctx, false /* isAck */, payload, ctx.newPromise());
ctx.flush();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer the caller do the flush. The only time explicit flushes are necessary here is for writes due to timers. For writes caused by reads, we do flush in onReadComplete. For writes coming from the application, it ends up flushing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


long gracefulShutdownPingTimeout = GRACEFUL_SHUTDOWN_PING_TIMEOUT_NANOS;
if (graceTimeInNanos != null) {
deadline = ticker.read() + graceTimeInNanos;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Count grace time starting at secondGoAwayAndClose(), since we'll still be accepting new requests until that point.

With that change, it also seems the ticker would no longer be necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Http2Error.NO_ERROR.code(),
ByteBufUtil.writeAscii(ctx.alloc(), goAwayMessage),
ctx.newPromise());
ctx.flush();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto remove. You only need the flush in the gracefulShutdownPingTimeout handling (not for the ping receiving).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

long savedGracefulShutdownTimeMillis = gracefulShutdownTimeoutMillis();
long gracefulShutdownTimeoutMillis = savedGracefulShutdownTimeMillis;
if (graceTimeInNanos != null) {
gracefulShutdownTimeoutMillis = TimeUnit.NANOSECONDS.toMillis(deadline - ticker.read());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this consulting deadline? I thought we agreed that graceTimeInNanos would be relative to the second GOAWAY.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a partial fix. Removing ticker is in the upcoming commit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@dapengzhang0
Copy link
Contributor Author

@ejona86 Thanks for the review. PTAL.

decoder().flowController().initialWindowSize(connection().connectionStream())));
}
} else if (data == GRACEFUL_SHUTDOWN_PING) {
if (gracefulShutdown == null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I remember why I put that comment. This is doing a check based on what is received. In your earlier response you said:

It will never throw a RuntimeException unless there's a bug in the code.

But the bug could be in the remote code, not in this code. That's why I had suggested a warning.

@dapengzhang0 dapengzhang0 added the kokoro:force-run Add this label to a PR to tell Kokoro to re-run all tests. Not generally necessary label Mar 28, 2018
@kokoro-team kokoro-team removed the kokoro:force-run Add this label to a PR to tell Kokoro to re-run all tests. Not generally necessary label Mar 28, 2018
@dapengzhang0 dapengzhang0 merged commit bdecdae into grpc:master Mar 28, 2018
@dapengzhang0 dapengzhang0 deleted the graceful branch May 2, 2018 17:14
@lock lock bot locked as resolved and limited conversation to collaborators Jan 18, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Netty server doesn't send multiple GOAWAYs during graceful shutdown

3 participants