GoawayFrame puts http2 connection in a bad state
tvolkert opened this issue · comments
Spawned from dart-lang/appengine#117
package:appengine
registers a single gcloud:DatastoreDB
instance upon server startup, which triggers the following objects to be persisted as part of its object graph:
- ↳ gcloud:DatastoreDB maintains a reference to a
gcloud:Datastore
- (implemented by
appengine:GrpcDatastoreImpl
)
- (implemented by
- ↳
appengine:GrpcDatastoreImpl
maintains a reference togrpc:ClientChannel
- ↳
grpc:ClientChannel
maintains a reference togrpc:Http2ClientConnection
- ↳
grpc:Http2ClientConnection
maintains a reference tohttp2:ClientTransportConnection
I'm seeing cases where the following code is hitting:
Lines 354 to 356 in 0484372
This causes the connection's state to get marked as IsFinishing/PassiveFinishing
. Then later, grpc tries to issue another request:
And it results in the following error:
Lines 461 to 463 in 0484372
Since the underlying http2 connection is retained by our server-wide connection to the datastore, every single subsequent HTTP request to my App Engine server that tries to talk to the datastore fails with this error ("gRPC Error (14, Error making call: Bad state: The http/2 connection is finishing and can therefore not be used to make new streams")
@sigurdm, maybe we can step through this sometime Monday/Tuesday, it feels like a failure to reconnect - in grpc, not sure why. I thought we had checked that it would reconnect :)
@tvolkert, is it all subsequent requests, or only the ones happening concurrently to the request that failed?
Does the connection continue to be broken minutes later too?
@jonasfj it is all subsequent requests - I still saw it happening for all requests 12 minutes after first occurrence, and then I switched traffic back over to the Go backend.
Generally speaking http/2 connections can go into finishing state for various reasons and you cannot make new streams on such a connection. So this situation has to be handled by the user of package:http2
, namely the grpc implementation.
The original grpc implementation in package:appengine/src/grpc_api_impl/grpc.dart handled this just fine.
Please see my comment on the original issue dart-lang/appengine#117 (comment).
Thanks Martin! Third time's a charm in filing this issue in the correct repo 😄 -- I'm gonna close this an consolidate all comments into grpc/grpc-dart#228