-
Notifications
You must be signed in to change notification settings - Fork 787
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Keep alive missing? #770
Comments
Can you provide a runnable sample that reproduces this problem? We don't believe the server should be terminating the connection in this situation, so it would help to see the full context of what you're doing. In addition, if you could enable more detailed logging using the following config in your appSettings.json that would help. {
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Trace",
"Grpc": "Debug"
}
}
} |
After further investigation this proves not to be the actual issue for me. Apologies for the confusion. I have |
This is something we will definitely need, as we expect our subscriptions to run indefinitely. |
@JamesNK @anurse Hi James, Andrew, I believe I might need keep alive functionality where I am implementing bidi and server to client streams. These would be long running, and there may be long periods of no messages, which is what I understand the keep alive ping/pong behaviour to be designed for - essentially to test that the connection has not been reset without either side knowing. Would this be a suitable use case for keep alive? If so I'd like to throw my vote in for including it with Grpc-net. Thanks. |
If it helps there is one C# project on GitHub which seems to have rolled their own grpc client code which allows them to set channeloptions on the underlying channel: Which uses this GatewayGrpc client: |
@JamesNK @anurse Hi again James, Andrew, can I ask where support for gRPC keepalive might be on your priority list? At present I am rolling my own heart beating, which is very much sub-optimal. I would love to rip out some of my code and use the underlying mechanism to get confidence that longstanding tcp connections are still connected. Thanks. |
At the moment it is low priority because we haven't had many people ask for it. What do you want built-in heart beats for? Is it perf, i.e. keeping the TCP connection open so there is not a delay reestablishing the connection after a pause? |
A combination of requiring long running streams for performance reasons, but I also require an up to date view of which streaming connections are still live as we require a client to have connections to certain streams before we allow them to perform operations against other endpoints. If we cannot guarantee the client connections are currently active then we cannot enforce policies which we require. |
@JamesNK I'm planning to switch to gRPC but this issue kept me back. My project has long-running idle connections and need to be responsive as soon as they are used. |
We are using keepalives in grpc core when exposing grpc services through AWS NLB load balancer, without them the load balancer would just non gracefully close tcp connections and grpc clients would get errors. My understanding is Azure load balancer works the same way. When running services in kubernetes it also has idle timeout settings (https://kubernetes.io/docs/reference/command-line-tools-reference/kube-proxy/) which will non gracefully terminate tcp connections as well. Keepalives really help in these scenarios which makes apps and services a lot more stable. |
@JamesNK Hi James - has any of the above feedback influenced how you are thinking about Keep Alive? |
I'm planning to investigate what options are in Grpc.Core, and what ones would be useful to have in grpc-dotnet. If people can give feedback on which settings are important, and why, then that would be useful. To set expectations: Adding new features to the gRPC on the server - including Kestrel - will be easier than the client. I can prioritize implementing server-side features myself. Client-side features that need to be added to HttpClient are done by a different team. They might not make the cut in the .NET 5 time-frame. |
Below I've included what my product is currently using to keep Azure load balancers alive when we have a lull in traffic and our gRPC channels don't have any active calls or messages. (The Azure load balancers will sometimes drop idle connections without sending RST packets to either endpoint.) We use keepalives to
As has been mentioned before, yes, we could do this by adding some sort of heartbeat in our application protocol. The keepalive functionality in the gRPC code library has, thus far, been sufficient.
This is an excerpt of the keepalive options that are set on a gRPC code channel.
ExtendedChannelOptions class is a collection of C# string constants for the gRPC code channel options. It's definition is below. |
@JamesNK As detailed in the previous post. For me the most useful would be the first 3 options:
|
@JamesNK here are the options that we normally use for keepalives on the client: var opts = new List<ChannelOption>();
opts.Add(new ChannelOption("grpc.keepalive_time_ms", connOptions.KeepaliveTimeout));
opts.Add(new ChannelOption("grpc.keepalive_timeout_ms", ConnectionOptions.DefaultKeepaliveWaitTimeout));
opts.Add(new ChannelOption("grpc.keepalive_permit_without_calls", 1));
opts.Add(new ChannelOption("grpc.http2.min_time_between_pings_ms", connOptions.TimeBetweenPings));
opts.Add(new ChannelOption("grpc.http2.max_pings_without_data", 0)); on the server this one is useful to disable keepalive policy if needed:
not strictly related to keepalives, but we also use |
Is the typical pattern here that the client is responsible for keeping the connection alive? i.e. the client pings the server on an interval and the server is only responsible for replying to the ping |
We run the pings in both directions so that both client and server can detect when traffic has disappeared into a black hole during idle times. (AFAIK, there's no setting to anticipate pings and update connectivity state if one hasn't been seen in a while.) For us, client pinging server would be more useful than server pinging clients. We do have bi-directional streaming, but the idle times are usually between calls, not while a call is active. (E.g., my service doesn't have long-lived calls pushing data to clients. Yet. 😉) |
I briefly looked into Grpc.Core's keep-alive pings a few months ago. The packets in Wireshark from pings indicated that they were connection level pings. The pings had a StreamID=0. I didn't see any stream level pings where the ping's StreamID=ActiveStreamID. Do pings serve any purpose when it comes to keeping streams alive? I am thinking about potentially long running calls on those streams like bi-directional streaming that might not actively be sending messages. |
AFAIK, it just keeps the TCP, TLS, and HTTP2 connection alive. (My product doesn't have long-lived streams.) To control stream/call lifetime, I think one needs to use deadlines. |
Ok. Envoy supports timing out individual streams - see I think to keep a long-running streaming call open in an environment where stream_idle_timeout is enabled you would need to send occasional dummy keepalive messages through gRPC. |
Proposal for APIs added to HttpClient - dotnet/runtime#31198 (comment) These could then be set when creating a handler for a gRPC channel. |
@JamesNK "Is the typical pattern here that the client is responsible for keeping the connection alive?" For me it's server as well. My server maintains client subscriptions and does work for each subscriber, so knowing when the connection is dropped and cleanup can occur is useful. |
Keep alive doesn't tell you when a connection is dropped. Its purpose it to send regular pings so connections are not closed from inactivity. |
But if you don't get a ping back surely that means the connection was
dropped? Unless the act of sending a ping re-establishes the connection.
…On Fri, May 29, 2020 at 12:17 AM James Newton-King ***@***.***> wrote:
Keep alive doesn't tell you when a connection is dropped. Its purpose it
to send regular pings so connections are not closed from inactivity.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#770 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AADY7B6LSDGQAOUXTKKEAQTRT3PC5ANCNFSM4KUSTWWA>
.
--
Sent from my regular computer
http://twitter.com/thefringeninja
http://www.thefringeninja.com/
|
If the client or server doesn't get a ping back in time then it means there is a problem and the connection will be dropped. What I meant is there is no API as part of this feature that will tell you a ping timed out and connection was dropped. |
If you have a server streaming endpoint and the client has keep alive
configured, should the connection become unusable, then wouldn't the
subsequent failed keep alive attempt from the client result in something
detectable in the client, such as an exception, or the termination of the
response stream?
…On Thu, 28 May 2020, 23:30 James Newton-King, ***@***.***> wrote:
But if you don't get a ping back surely that means the connection was
dropped?
If the client or server doesn't get a ping back in time then it means
there is a problem and the connection will be dropped. What I meant is
there is no API as part of this feature that will tell you a ping timed out
and connection was dropped.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#770 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABEA7AOMA3KRQZ7X5AWO5OTRT3QYPANCNFSM4KUSTWWA>
.
|
If you were awaiting the response stream for more data and the connection was terminated then you would immediately get an error that the connection has closed. |
How does that work? If the client is waiting to receive data can it not be
waiting forever if something like an intermediate router fails? The server
at some point tries to send data, fails, and disconnects, but the client
would wait on the half open connection?
This is one of the scenarios I wanted to solve with keep alive: the client
instead regularly tests connectivity and fails faster if the connection has
become half open.
…On Fri, 29 May 2020, 00:24 James Newton-King, ***@***.***> wrote:
If you were awaiting the response stream for more data and the connection
was terminated then you would immediately get an error that the connection
has closed.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#770 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABEA7ALSPRT5FFFAZ56TR2DRT3XCXANCNFSM4KUSTWWA>
.
|
Operations awaiting HttpClient's request and response stream will error if the TCP connection is broken. |
Can you point me in the right direction to read about this? I don't
understand how this is possible during periods of inactivity, unless there
is some sort of packet to check whether the peer can be reached. This was
what I believed keep alive packets would probe. Thanks.
…On Fri, 29 May 2020, 01:19 James Newton-King, ***@***.***> wrote:
Operations awaiting HttpClient's request and response stream will error if
the TCP connection is broken.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#770 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABEA7ALEBMOGWZYJRYGZ54DRT35SNANCNFSM4KUSTWWA>
.
|
@JamesNK To clarify the above question: assume a streaming server. The client is awaiting the next response when an intermediary router is powered down and the connection is left half open. The server detects this and closes, but what happens with the client? What stops the client from sitting and waiting forever? |
@JuliusSweetland You're right that it's possible for one side of an idle TCP connection to disconnect without the other side observing it. Without any keep alives or timeouts a connection can stay in this state indefinitely. Keep-alives could avoid this. In the meantime, you could have the client periodically send application-level pings/keep-alives or somethings similar. |
Thanks @halter73 so I believe, between the discussed use cases and the fact that it is possible for the recipient of a stream (client or server) to be waiting for a message which isn't coming, that gRPC Core keep alive functionality is required on both the client and server side. @JamesNK do you agree? @halter73 I am using manual pings and monitoring in both directions for my bi directional streaming use case, but it would be great to simplify my code and push this down to a lower level. |
Keep alive pings are supported in 5.0. This can be closed. Best practice documentation related to performance: https://docs.microsoft.com/en-us/aspnet/core/grpc/performance?view=aspnetcore-5.0#keep-alive-pings |
Keepalive options in SocketsHttpHandler don't seem to be available in dotnet-core |
.NET 5.0 is .NET Core 5.0. It's just rebranded. |
Can we have grpc.max-idle-connection-timeout. Otherwise the grpc server will cut off connection 60s inactivity and cause stream remove error in the grpc client. This is not expected when you want have stable steaming rpc. |
For some reason my question text was removed from the question - redoing it here.
Is there a way to keep the connection between client and server alive in a C# gRPC app? My scenario is a bidirectional streaming one (essentially the FullStockTicker demo). What I see is that the server closes the HTTP/2 connection after a few minutes. I have tried to find a way to set the keep alive flag, but that does not seem possible from C#.
I am using Grpc.AspNetCore (2.27.0), Grpc.Tools (2.27.0), Google.Protobuf (3.11.3) and generated clients.
The text was updated successfully, but these errors were encountered: