-
Notifications
You must be signed in to change notification settings - Fork 861
fix(connector): add gRPC keepalive and default UNAVAILABLE retry policy #7458
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
base: main
Are you sure you want to change the base?
Changes from 1 commit
7829e6a
ddc8dde
d2f9024
73ab5df
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,13 +4,15 @@ import ( | |
| "context" | ||
| "crypto/x509" | ||
| "strings" | ||
| "time" | ||
|
|
||
| "golang.org/x/exp/maps" | ||
| "google.golang.org/grpc" | ||
| "google.golang.org/grpc/codes" | ||
| "google.golang.org/grpc/credentials" | ||
| "google.golang.org/grpc/credentials/insecure" | ||
| "google.golang.org/grpc/grpclog" | ||
| "google.golang.org/grpc/keepalive" | ||
|
|
||
| "google.golang.org/grpc/status" | ||
|
|
||
| "github.com/flyteorg/flyte/v2/flytestdlib/config" | ||
|
|
@@ -20,6 +22,42 @@ import ( | |
|
|
||
| const defaultTaskTypeVersion = 0 | ||
|
|
||
| // defaultGRPCServiceConfig is the gRPC service config applied to a connector | ||
| // connection when its Deployment does not set DefaultServiceConfig. It enables | ||
| // round-robin load balancing across connector replicas and retries transient | ||
| // UNAVAILABLE failures so a single dropped connection does not fail the task. | ||
| // | ||
| // Connector traffic frequently flows through an L7 gateway (e.g. the | ||
| // Knative/Kourier Envoy gateway), which reaps idle HTTP/2 connections and sends | ||
| // GOAWAY/drain on routing changes. The cached *grpc.ClientConn then surfaces | ||
| // "error reading server preface: ... use of closed network connection" on the | ||
| // next RPC; retrying UNAVAILABLE absorbs that blip in-band. retryThrottling | ||
| // stops retries from hammering a connector that is genuinely down. | ||
| const defaultGRPCServiceConfig = `{ | ||
| "loadBalancingConfig": [{"round_robin":{}}], | ||
| "methodConfig": [{ | ||
| "name": [{"service": "flyteidl2.connector.AsyncConnectorService"}], | ||
| "retryPolicy": { | ||
| "maxAttempts": 4, | ||
| "initialBackoff": "0.2s", | ||
| "maxBackoff": "3s", | ||
| "backoffMultiplier": 2.0, | ||
| "retryableStatusCodes": ["UNAVAILABLE"] | ||
| } | ||
| }], | ||
| "retryThrottling": {"maxTokens": 10, "tokenRatio": 0.1} | ||
| }` | ||
|
|
||
| // gRPC client keepalive parameters. Pinging below the gateway's idle timeout | ||
| // keeps long-lived connector connections from being reaped while idle (the | ||
| // connector metadata poll and task RPCs are bursty), and proactively detects a | ||
| // half-dead connection instead of discovering it on the next RPC. | ||
| var connectorKeepalive = keepalive.ClientParameters{ | ||
| Time: 30 * time.Second, | ||
| Timeout: 10 * time.Second, | ||
| PermitWithoutStream: true, | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch — this is valid, and the enforcement is cross-language (grpcio/Python servers run on C-core, whose defaults match grpc-go: Fixed: keepalive is now opt-in per |
||
| } | ||
|
|
||
| type Connector struct { | ||
| // ConnectorDeployment is the connector deployment where this connector is running. | ||
| ConnectorDeployment *Deployment | ||
|
|
@@ -50,9 +88,13 @@ func getGrpcConnection(ctx context.Context, connector *Deployment) (*grpc.Client | |
| opts = append(opts, grpc.WithTransportCredentials(creds)) | ||
| } | ||
|
|
||
| if len(connector.DefaultServiceConfig) != 0 { | ||
| opts = append(opts, grpc.WithDefaultServiceConfig(connector.DefaultServiceConfig)) | ||
| serviceConfig := connector.DefaultServiceConfig | ||
| if len(serviceConfig) == 0 { | ||
| serviceConfig = defaultGRPCServiceConfig | ||
| } | ||
| opts = append(opts, grpc.WithDefaultServiceConfig(serviceConfig)) | ||
|
Comment on lines
+75
to
+79
|
||
|
|
||
| opts = append(opts, grpc.WithKeepaliveParams(connectorKeepalive)) | ||
|
|
||
| var err error | ||
| conn, err := grpc.Dial(connector.Endpoint, opts...) //nolint: staticcheck | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, but this isn't needed for the grpc-go version we use (v1.81.1). The core
google.golang.org/grpcpackage already registersround_robinfor us:clientconn.go(which ispackage grpc) hasand
roundrobin'sinit()callsbalancer.Register(...). Since this file already importsgoogle.golang.org/grpc, the balancer is registered as soon as the package loads — no separate blank import required. The manual blank import was only necessary in much older grpc-go releases (pre ~v1.36) before that import was folded intoclientconn.go.Also,
{"loadBalancingConfig":[{"round_robin":{}}]}was already the prior default service config and is in use in production, so there's no silent fallback here.