diff --git a/geps/gep-1742.md b/geps/gep-1742.md index b2b2b5b641..7f7d07603e 100644 --- a/geps/gep-1742.md +++ b/geps/gep-1742.md @@ -1,7 +1,7 @@ -# GEP-1742: Timeouts +# GEP-1742: HTTPRoute Timeouts * Issue: [#1742](https://github.com/kubernetes-sigs/gateway-api/issues/1742) -* Status: Provisional +* Status: Implementable (See status definitions [here](overview.md#status).) @@ -12,12 +12,12 @@ timeouts for different types of connection. ## Goals -- Create some method to configure some timeouts +- Create some method to configure some timeouts. - Timeout config must be applicable to most if not all Gateway API implementations. ## Non-Goals -- TBD +- A standard API for every possible timeout that implementations may support. ## Introduction @@ -298,16 +298,190 @@ Could not find any HTTP specific timeouts. PRs welcomed. 😊 Could not find any HTTP specific timeouts. PRs welcomed. 😊 - ## API -TBD. +The above diagrams show that there are many different kinds of configurable timeouts +supported by Gateway implementations: connect, idle, request, upstream, downstream. +Although there may be opportunity for the specification of a common API for more of +them in the future, this GEP will focus on the L7 timeouts in HTTPRoutes that are +most valuable to clients. + +From the above analysis, it appears that most implementations are capable of +supporting the configuration of simple client downstream request timeouts on HTTPRoute +rules. This is a relatively small addition that would benefit many users. + +Some implementations support configuring a timeout for individual backend requests, +separate from the overall client request timeout. This is particularly useful if a +client HTTP request to a gateway can result in more than one call from the gateway +to the destination backend service, for example, if automatic retries are supported. +Adding support for this would also benefit many users. + +### Timeout values + +There are 2 kinds of timeouts that can be configured in an `HTTPRouteRule`: + +1. `timeouts.request` is the timeout for the Gateway API implementation to send a + response to a client HTTP request. Whether the gateway starts the timeout before + or after the entire client request stream has been received, is implementation dependent. + This field is optional `Extended` support. +1. `timeouts.backendRequest` is a timeout for a single request from the gateway to a backend. + This field is optional `Extended` support. Typically used in conjuction with retry configuration, + if supported by an implementation. + Note that retry configuration will be the subject of a separate GEP (GEP-1731). + +```mermaid +sequenceDiagram + participant C as Client + participant P as Proxy + participant U as Upstream + C->>P: Connection Started + note left of P: timeouts.request start time (min) + C->>P: Starts sending Request + C->>P: Finishes Headers + C->>P: Finishes request + note left of P: timeouts.request start time (max) + P->>U: Connection Started + note right of P: timeouts.backendRequest start time + P->>U: Starts sending Request + P->>U: Finishes request + P->>U: Finishes Headers + U->>P: Starts Response + U->>P: Finishes Headers + note right of P: timeouts.backendRequest end time + note left of P: timeouts.request end time + U->>P: Finishes Response + note right of P: Repeat if retry + P->>C: Starts Response + P->>C: Finishes Headers + P->>C: Finishes Response + Note right of P: Repeat if connection sharing + U->>C: Connection ended +``` + +Both timeout fields are string duration values as specified by +[Golang time.ParseDuration](https://pkg.go.dev/time#ParseDuration) and MUST be >= 1ms +or 0 to disable (no timeout). + +### GO + +```go +type HTTPRouteRule struct { + // Timeouts defines the timeouts that can be configured for an HTTP request. + // + // Support: Extended + // + // +optional + // + Timeouts *HTTPRouteTimeouts `json:"timeouts,omitempty"` + + // ... +} + +// HTTPRouteTimeouts defines timeouts that can be configured for an HTTPRoute. +// Timeout values are formatted like 1h/1m/1s/1ms as parsed by Golang time.ParseDuration +// and MUST BE >= 1ms or 0 to disable (no timeout). +type HTTPRouteTimeouts struct { + // Request specifies the duration for processing an HTTP client request after which the + // gateway will time out if unable to send a response. + // + // For example, setting the `rules.timeouts.request` field to the value `10s` in an + // `HTTPRoute` will cause a timeout if a client request is taking longer than 10 seconds + // to complete. + // + // This timeout is intended to cover as close to the whole request-response transaction + // as possible although an implementation MAY choose to start the timeout after the entire + // request stream has been received instead of immediately after the transaction is + // initiated by the client. + // + // When this field is unspecified, request timeout behavior is implementation-dependent. + // + // Support: Extended + // + // +optional + // +kubebuilder:validation:Format=duration + Request *metav1.Duration `json:"request,omitempty"` + + // BackendRequest specifies a timeout for an individual request from the gateway + // to a backend service. This covers the time from when the request first starts being + // sent from the gateway to when the full response has been received from the backend. + // + // An entire client HTTP transaction with a gateway, covered by the Request timeout, + // may result in more than one call from the gateway to the destination backend service, + // for example, if automatic retries are supported. + // + // Because the Request timeout encompasses the BackendRequest timeout, + // the value of BackendRequest defaults to and must be <= the value of Request timeout. + // + // Support: Extended + // + // +optional + // +kubebuilder:validation:Format=duration + BackendRequest *metav1.Duration `json:"backendRequest,omitempty"` +} +``` + +### YAML + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: timeout-example +spec: + ... + rules: + - backendRefs: + - name: some-service + port: 8080 + timeouts: + request: 10s + backendRequest: 2s +``` + +### Conformance Details + +Gateway implementations can indicate support for the optional behavior in this GEP using +the following feature names: + +- `HTTPRouteRequestTimeout`: supports `rules.timeouts.request` in an `HTTPRoute`. +- `HTTPRouteBackendTimeout`: supports `rules.timeouts.backendRequest` in an `HTTPRoute`. ## Alternatives -(List other design alternatives and why we did not go in that -direction) +Timeouts could be configured using policy attachments or in objects other than `HTTPRouteRule`. + +### Policy Attachment + +Instead of configuring timeouts directly on an API object, they could be configured using policy +attachments. The advantage to this approach would be that timeout policies can be not only +configured for an `HTTPRouteRule`, but can also be added/overriden at a more fine +(e.g., `HTTPBackendRef`) or course (e.g. `HTTPRoute`) level of granularity. + +The downside, however, is complexity introduced for the most common use case, adding a simple +timeout for an HTTP request. Setting a single field in the route rule, instead of needing to +create a policy resource, for this simple case seems much better. + +In the future, we could consider using policy attachments to configure less common kinds of +timeouts that may be needed, but it would probably be better to instead extend the proposed API +to support those timeouts as well. + +The default values of the proposed timeout fields could also be overriden +using policy attachments in the future. For example, a policy attachment could be used to set the +default value of `rules.timeouts.request` for all routes under an `HTTPRoute` or `Gateway`. + +### Other API Objects + +The new timeouts field could be added to a different API struct, instead of `HTTPRouteRule`. + +Putting it on an `HTTPBackendRef`, for example, would allow users to set different timeouts for different +backends. This is a feature that we believe has not been requested by existing proxy or service mesh +clients and is also not implementable using available timeouts of most proxies. + +Another alternative is to move the timeouts configuration up a level in the API to `HTTPRoute`. This +would be convenient when a user wants the same timeout on all rules, but would be overly restrictive. +Using policy attachments to override the default timeout value for all rules, as described in the +previous section, is likely a better way to handle timeout configuration above the route rule level. ## References diff --git a/mkdocs.yml b/mkdocs.yml index dadbf44682..22621c55d8 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -84,8 +84,6 @@ nav: - geps/gep-735.md - geps/gep-1282.md - Provisional: - - geps/gep-1742.md - - geps/gep-1426.md - geps/gep-1324.md - geps/gep-1619.md - geps/gep-1897.md @@ -93,6 +91,7 @@ nav: - Prototyping: - geps/gep-1709.md - Implementable: + - geps/gep-1742.md - geps/gep-1686.md - geps/gep-1426.md - Experimental: