aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@yahooinc.com>2023-04-26 15:40:04 +0200
committerBjørn Christian Seime <bjorncs@yahooinc.com>2023-04-26 15:40:04 +0200
commit0a7a694c87cd6268f78fd6eeb3a103c2c4e4ea47 (patch)
treeb098969113933fa175a800cfcc023db6b91a32f1
parentbd499fd3722bb2375d3e1219e2986d441d112d48 (diff)
Use graceful GOAWAY allowing all in-flight requests to complete
Original code used lastRemoteStreamId in GOAWAY frame that would cause inflight requests not yet received to be rejected.
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestDispatch.java22
1 files changed, 12 insertions, 10 deletions
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestDispatch.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestDispatch.java
index b4c933c1168..4cdbab5f89b 100644
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestDispatch.java
+++ b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestDispatch.java
@@ -17,7 +17,8 @@ import jakarta.servlet.AsyncEvent;
import jakarta.servlet.AsyncListener;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
-import org.eclipse.jetty.http2.ErrorCode;
+import org.eclipse.jetty.http2.HTTP2Session;
+import org.eclipse.jetty.http2.frames.GoAwayFrame;
import org.eclipse.jetty.http2.server.HTTP2ServerConnection;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EofException;
@@ -159,7 +160,7 @@ class HttpRequestDispatch {
Connection connection = RequestUtils.getConnection(request);
if (maxRequestsPerConnection > 0) {
if (connection.getMessagesIn() >= maxRequestsPerConnection) {
- gracefulShutdown(connection, "max-req-per-conn-exceeded");
+ gracefulShutdown(connection);
}
}
double maxConnectionLifeInSeconds = connectorConfig.maxConnectionLife();
@@ -168,19 +169,20 @@ class HttpRequestDispatch {
Instant expiredAt = Instant.ofEpochMilli((long) (createdAt + maxConnectionLifeInSeconds * 1000));
boolean isExpired = Instant.now().isAfter(expiredAt);
if (isExpired) {
- gracefulShutdown(connection, "max-conn-life-exceeded");
+ gracefulShutdown(connection);
}
}
}
- private static void gracefulShutdown(Connection connection, String reason) {
- if (connection instanceof HttpConnection) {
- HttpConnection http1 = (HttpConnection) connection;
+ private static void gracefulShutdown(Connection connection) {
+ if (connection instanceof HttpConnection http1) {
http1.getGenerator().setPersistent(false);
- } else if (connection instanceof HTTP2ServerConnection) {
- HTTP2ServerConnection http2 = (HTTP2ServerConnection) connection;
- // Signal Jetty to do a graceful connection shutdown with GOAWAY frame
- http2.getSession().close(ErrorCode.NO_ERROR.code, reason, Callback.NOOP);
+ } else if (connection instanceof HTTP2ServerConnection http2) {
+ // Signal Jetty to do a graceful shutdown of HTTP/2 connection.
+ // Graceful shutdown implies a GOAWAY frame with 'Error Code' = 'NO_ERROR' and 'Last-Stream-ID' = 2^31-1.
+ // In-flight requests will be allowed to complete before connection is terminated.
+ // See https://datatracker.ietf.org/doc/html/rfc9113#name-goaway for details
+ ((HTTP2Session)http2.getSession()).goAway(GoAwayFrame.GRACEFUL, Callback.NOOP);
}
}