Skip to content

Commit 046e02b

Browse files
authored
okhttp: forceful close after MAX_CONNECTION_AGE_GRACE_TIME (#9968)
1 parent e04c6ec commit 046e02b

File tree

2 files changed

+30
-5
lines changed

2 files changed

+30
-5
lines changed

okhttp/src/main/java/io/grpc/okhttp/OkHttpServerTransport.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import java.util.concurrent.TimeUnit;
6161
import java.util.logging.Level;
6262
import java.util.logging.Logger;
63+
import javax.annotation.Nullable;
6364
import javax.annotation.concurrent.GuardedBy;
6465
import okio.Buffer;
6566
import okio.BufferedSource;
@@ -73,6 +74,9 @@ final class OkHttpServerTransport implements ServerTransport,
7374
ExceptionHandlingFrameWriter.TransportExceptionHandler, OutboundFlowController.Transport {
7475
private static final Logger log = Logger.getLogger(OkHttpServerTransport.class.getName());
7576
private static final int GRACEFUL_SHUTDOWN_PING = 0x1111;
77+
78+
private static final long GRACEFUL_SHUTDOWN_PING_TIMEOUT_NANOS = TimeUnit.SECONDS.toNanos(1);
79+
7680
private static final int KEEPALIVE_PING = 0xDEAD;
7781
private static final ByteString HTTP_METHOD = ByteString.encodeUtf8(":method");
7882
private static final ByteString CONNECT_METHOD = ByteString.encodeUtf8("CONNECT");
@@ -132,6 +136,8 @@ final class OkHttpServerTransport implements ServerTransport,
132136
/** Non-{@code null} when waiting for forceful close GOAWAY to be sent. */
133137
@GuardedBy("lock")
134138
private ScheduledFuture<?> forcefulCloseTimer;
139+
@GuardedBy("lock")
140+
private Long gracefulShutdownPeriod = null;
135141

136142
public OkHttpServerTransport(Config config, Socket bareSocket) {
137143
this.config = Preconditions.checkNotNull(config, "config");
@@ -250,15 +256,16 @@ public void data(boolean outFinished, int streamId, Buffer source, int byteCount
250256

251257
@Override
252258
public void shutdown() {
253-
shutdown(TimeUnit.SECONDS.toNanos(1L));
259+
shutdown(null);
254260
}
255261

256-
private void shutdown(Long graceTimeInNanos) {
262+
private void shutdown(@Nullable Long gracefulShutdownPeriod) {
257263
synchronized (lock) {
258264
if (gracefulShutdown || abruptShutdown) {
259265
return;
260266
}
261267
gracefulShutdown = true;
268+
this.gracefulShutdownPeriod = gracefulShutdownPeriod;
262269
if (frameWriter == null) {
263270
handshakeShutdown = true;
264271
GrpcUtil.closeQuietly(bareSocket);
@@ -267,7 +274,8 @@ private void shutdown(Long graceTimeInNanos) {
267274
// we also set a timer to limit the upper bound in case the PING is excessively stalled or
268275
// the client is malicious.
269276
secondGoawayTimer = scheduledExecutorService.schedule(
270-
this::triggerGracefulSecondGoaway, graceTimeInNanos, TimeUnit.NANOSECONDS);
277+
this::triggerGracefulSecondGoaway,
278+
GRACEFUL_SHUTDOWN_PING_TIMEOUT_NANOS, TimeUnit.NANOSECONDS);
271279
frameWriter.goAway(Integer.MAX_VALUE, ErrorCode.NO_ERROR, new byte[0]);
272280
frameWriter.ping(false, 0, GRACEFUL_SHUTDOWN_PING);
273281
frameWriter.flush();
@@ -289,6 +297,10 @@ private void triggerGracefulSecondGoaway() {
289297
} else {
290298
frameWriter.flush();
291299
}
300+
if (gracefulShutdownPeriod != null) {
301+
forcefulCloseTimer = scheduledExecutorService.schedule(
302+
this::triggerForcefulClose, gracefulShutdownPeriod, TimeUnit.NANOSECONDS);
303+
}
292304
}
293305
}
294306

okhttp/src/test/java/io/grpc/okhttp/OkHttpServerTransportTest.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ public void startThenShutdown() throws Exception {
155155
@Test
156156
public void maxConnectionAge() throws Exception {
157157
serverBuilder.maxConnectionAge(5, TimeUnit.SECONDS)
158-
.maxConnectionAgeGrace(1, TimeUnit.SECONDS);
158+
.maxConnectionAgeGrace(3, TimeUnit.SECONDS);
159159
initTransport();
160160
handshake();
161161
clientFrameWriter.headers(1, Arrays.asList(
@@ -169,8 +169,20 @@ public void maxConnectionAge() throws Exception {
169169
new Header("some-client-sent-trailer", "trailer-value")));
170170
pingPong();
171171
fakeClock.forwardNanos(TimeUnit.SECONDS.toNanos(6)); // > 1.1 * 5
172-
fakeClock.forwardNanos(TimeUnit.SECONDS.toNanos(1));
173172
verifyGracefulShutdown(1);
173+
pingPong();
174+
fakeClock.forwardNanos(TimeUnit.SECONDS.toNanos(3));
175+
assertThat(socket.isClosed()).isTrue();
176+
}
177+
178+
@Test
179+
public void maxConnectionAge_shutdown() throws Exception {
180+
serverBuilder.maxConnectionAge(5, TimeUnit.SECONDS)
181+
.maxConnectionAgeGrace(3, TimeUnit.SECONDS);
182+
initTransport();
183+
handshake();
184+
shutdownAndTerminate(0);
185+
assertThat(fakeClock.numPendingTasks()).isEqualTo(0);
174186
}
175187

176188
@Test
@@ -1369,6 +1381,7 @@ public synchronized void close() throws IOException {
13691381
// PipedInputStream can only be woken by PipedOutputStream, so PipedOutputStream.close() is
13701382
// a better imitation of Socket.close().
13711383
inputStreamSource.close();
1384+
super.close();
13721385
}
13731386
}
13741387

0 commit comments

Comments
 (0)