Kreinoee opened a new pull request, #1316:
URL: https://github.com/apache/pekko-http/pull/1316
### Motivation
Long-lived HTTP/2 connections (as used by gRPC) lead to an uneven load
distribution across server
instances: clients stay connected to the instances they found at connect
time, and instances added
later (after a scale-out or a rolling deploy) receive no share of the
existing traffic. The server
is the side that can retire a connection gracefully, via GOAWAY. grpc-java
offers this as
`maxConnectionAge`; pekko-http has no equivalent (akka/akka-grpc#967 is the
corresponding request
on the Akka side).
### Modification
Add a `pekko.http.server.http2.max-connection-age` setting, default
`infinite` (disabled). When a
server connection reaches the configured age, the existing graceful
termination path is triggered:
GOAWAY(NO_ERROR) is sent, streams that are in flight complete normally,
streams opened after the
GOAWAY are refused with RST_STREAM(REFUSED_STREAM), and the connection is
closed once no streams
remain.
The age is jittered per connection by a configurable fraction,
`max-connection-age-jitter` (default
0.1 = +/- 10%, the value grpc-java applies; 0 disables jitter), so that
connections that were opened
together, for example after a deploy, are not all closed at the same time.
`triggerTermination` now accepts an infinite deadline, in which case no
forced-close timer is
scheduled. Also corrects the termination debug log, which printed the timer
key instead of the
deadline.
### Result
Operators can cap the lifetime of server-side HTTP/2 connections to
rebalance long-lived
connections across server instances. Behavior is unchanged by default.
Verified against a real grpc-java (1.75.0) client: with `max-connection-age
= 5s` on a pekko-http
server, a client issuing a unary call every 200 ms for 16 s observed 0
failures across 3 connection
retirements (the server saw 4 distinct client connections), and a unary call
that was in flight when
the GOAWAY was sent completed normally on the connection being drained.
### Tests
- `sbt "http2-tests/test"`: 376 tests pass, including 2 new directional
tests for
max-connection-age in `Http2ServerSpec` (GOAWAY(NO_ERROR) + connection
close on an idle
connection; in-flight stream completes and late stream is refused)
- `sbt "+http-core/mimaReportBinaryIssues"`: clean, with 5 new
`ReversedMissingMethodProblem`
filters for the added methods on `Http2ServerSettings`
(`@ApiMayChange`/`@DoNotInherit`) and the
internal `Http2Demux`
- `sbt scalafmtCheckAll scalafmtSbtCheck`: clean
- `sbt headerCreateAll`: no changes
- `sbt docs/paradox`: builds (remaining warnings are pre-existing and
unrelated)
- `sbt validatePullRequest`: passes
- `sbt sortImports`: environment failure unrelated to this change
(`http/scalafixAll` fails with
`NoSuchMethodError` in scala.meta on a clean checkout of `main` too); the
files changed here are
sort-clean
- manual end-to-end check against grpc-java 1.75.0 (see Result)
### References
None - no pekko-http issue tracks this; akka/akka-grpc#967 is the equivalent
request against
akka-http/akka-grpc.
A companion PR targets 1.4.x: #BACKPORT_PR_NUMBER. The `@since` tags follow
each branch's line
(`2.0.0` here, `1.4.1` there), matching how max-header-list-size (#1247) was
tagged on the two
branches. Is that per-branch tagging actually the intended convention? It
leaves `main` claiming a
later version than the first release that will carry the API. If you prefer
`1.4.1` on both
branches, we will align them.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]