Description
I am hoping to get my head around server side keepalive settings in grpc-dotnet.
Scenario
Push based notifications. The client starts a streaming call which they expect to be long lived (for the duration of the program). The server can send push notifications via streaming to the client. The stream can become idle for long periods of time if there are no new notifications to be sent, but the connection should still be kept "warm".
This is running in an environment with a network firewall that will kill connections without traffic for an hour.
In this case, I have an ASP.NET 8 Server, and a Python Client.
Problem
I can't find definitive guidance on how to configure both sides for the above scenario. I am getting an error on the client after an hour of inactivity:
status = StatusCode.UNAVAILABLE
details = "Socket closed"
debug_error_string = "UNKNOWN:Error received from peer"
I have done a fair amount of extra reading:
- https://grpc.io/docs/guides/keepalive/
- https://learn.microsoft.com/en-us/aspnet/core/grpc/performance?view=aspnetcore-8.0#keep-alive-pings
- Keepalive settings and their counterparts in grpc docs #2313
- Keep alive missing? #770
- Additional KeepAlive settings #1096
- HTTP2 KeepAlive/PING control support #577
- configurable HTTP/2 PING timeouts on kestrel dotnet/aspnetcore#15104
gRPC docs highlight the importance of server and client settings being configured together. What I find somewhat confusing is that many of the keepalive configurations do not seem to be settable via the ASP.NET server e.g:
- keepalive_time_ms
- keepalive_permit_without_calls
- max_pings_without_data
It seems the explanation for this is that Kestrel handles keepalive itself (which I think is enabled by default?). My confusion probably stems from my lack of understanding about Kestrel. But I would appreciate it if someone could point me in the right direction.