You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When using HTTP/2 with a Connection Pool, an HTTP/2 server may occassionally send our reactor-netty client a GOAWAY frame indicating the last stream ID it will accept. In my use case, I am communicating with an nginx server, which by default will only allow 1000 requests on a single connection before it closes it by sending a GOAWAY.
Expected Behavior
After a GOAWAY frame is received and the last stream id is reached, the Pool should eventually stop returning that Connection from the Pool (even without setting or waiting for ConnectionPoolSpec#maxLifeTime).
If I have a retrySpec somewhere downstream of this client usage, subsequent attempts should proceed with a different Connection.
Actual Behavior
The Connection stays in the Pool, and subsequent retries that use the same Connection immediately fail with PrematureCloseException.
The main idea is to first set up a pool with a single HTTP/2 connection that can not be gracefully killed (no max lifetime, graceful shutdown with unlimited timeout, one stream that is held open).
Then, issue another request for which the web client has retry logic and the server will initiate the graceful shutdown on the connection.
If the retry happens after GOAWAY is processed, then you'll see messages like: io.netty.handler.codec.http2.Http2Exception$StreamException: Cannot create stream 7 greater than Last-Stream-ID 5 from GOAWAY
where that stream ID corresponds to the retry number (e.g. all the way up to 205 for 100 retries). That exception bubbles up in reactor-netty as reactor.netty.http.client.PrematureCloseException: Connection prematurely closed BEFORE response
That indicates the request with retries is continuously checking out the same PooledConnection, which remains in the pool despite not really being usable for new streams.
Possible Solution
I feel like this kind of PrematureCloseException belongs in the same category of exception that was handled by #2140, where the Connection is no longer marked as persistent and is summarily removed from the pool.
Your Environment
Reactor Netty version:
Obseved in 1.0.17, reproduced on 1.1.0-M5 snapshot (3917290)
JVM version:
Corretto-18.0.0.37.1
The text was updated successfully, but these errors were encountered:
According to the specification
https://www.rfc-editor.org/rfc/rfc9113.html#section-6.8
`Receivers of a GOAWAY frame MUST NOT open additional streams on the connection`
Reactor Netty by default is running with graceful shutdown which means that `GOAWAY`
might be received and the connection to be still alive.
`Http2Pool` should consider this use case and stop offering a connection that received `GOAWAY`.
Fixes#2396
When using HTTP/2 with a Connection Pool, an HTTP/2 server may occassionally send our reactor-netty client a GOAWAY frame indicating the last stream ID it will accept. In my use case, I am communicating with an nginx server, which by default will only allow 1000 requests on a single connection before it closes it by sending a GOAWAY.
Expected Behavior
After a GOAWAY frame is received and the last stream id is reached, the Pool should eventually stop returning that Connection from the Pool (even without setting or waiting for ConnectionPoolSpec#maxLifeTime).
If I have a retrySpec somewhere downstream of this client usage, subsequent attempts should proceed with a different Connection.
Actual Behavior
The Connection stays in the Pool, and subsequent retries that use the same Connection immediately fail with PrematureCloseException.
Steps to Reproduce
Test case here:
main...asw12:reactor-netty:bad_connection_reuse_after_h2_goaway
The main idea is to first set up a pool with a single HTTP/2 connection that can not be gracefully killed (no max lifetime, graceful shutdown with unlimited timeout, one stream that is held open).
Then, issue another request for which the web client has retry logic and the server will initiate the graceful shutdown on the connection.
If the retry happens after GOAWAY is processed, then you'll see messages like:
io.netty.handler.codec.http2.Http2Exception$StreamException: Cannot create stream 7 greater than Last-Stream-ID 5 from GOAWAY
where that stream ID corresponds to the retry number (e.g. all the way up to 205 for 100 retries). That exception bubbles up in reactor-netty as
reactor.netty.http.client.PrematureCloseException: Connection prematurely closed BEFORE response
That indicates the request with retries is continuously checking out the same PooledConnection, which remains in the pool despite not really being usable for new streams.
Possible Solution
I feel like this kind of PrematureCloseException belongs in the same category of exception that was handled by #2140, where the Connection is no longer marked as persistent and is summarily removed from the pool.
Your Environment
Reactor Netty version:
Obseved in 1.0.17, reproduced on 1.1.0-M5 snapshot (3917290)
JVM version:
Corretto-18.0.0.37.1
The text was updated successfully, but these errors were encountered: