Skip to content

Commit c4b189d

Browse files
committed
feat: support stream idle timeout
1 parent 4140f61 commit c4b189d

11 files changed

+416
-0
lines changed

api/v1alpha1/timeout_types.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,10 @@ type HTTPClientTimeout struct {
8181
//
8282
// +optional
8383
IdleTimeout *gwapiv1.Duration `json:"idleTimeout,omitempty"`
84+
85+
// The stream idle timeout defines the amount of time a stream can exist without any upstream or downstream activity.
86+
// Default: 5 minutes.
87+
//
88+
// +optional
89+
StreamIdleTimeout *gwapiv1.Duration `json:"streamIdleTimeout,omitempty"`
8490
}

internal/gatewayapi/clienttrafficpolicy.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,16 @@ func buildClientTimeout(clientTimeout *egv1a1.ClientTimeout) (*ir.ClientTimeout,
603603
Duration: d,
604604
}
605605
}
606+
607+
if clientTimeout.HTTP.StreamIdleTimeout != nil {
608+
d, err := time.ParseDuration(string(*clientTimeout.HTTP.StreamIdleTimeout))
609+
if err != nil {
610+
return nil, fmt.Errorf("invalid HTTP StreamIdleTimeout value %s", *clientTimeout.HTTP.StreamIdleTimeout)
611+
}
612+
irHTTPTimeout.StreamIdleTimeout = &metav1.Duration{
613+
Duration: d,
614+
}
615+
}
606616
irClientTimeout.HTTP = irHTTPTimeout
607617
}
608618

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
clientTrafficPolicies:
2+
- apiVersion: gateway.envoyproxy.io/v1alpha1
3+
kind: ClientTrafficPolicy
4+
metadata:
5+
namespace: envoy-gateway
6+
name: target-gateway
7+
spec:
8+
targetRef:
9+
group: gateway.networking.k8s.io
10+
kind: Gateway
11+
name: gateway
12+
sectionName: http-1
13+
timeout:
14+
http:
15+
requestReceivedTimeout: "5s"
16+
streamIdleTimeout: "1h"
17+
gateways:
18+
- apiVersion: gateway.networking.k8s.io/v1
19+
kind: Gateway
20+
metadata:
21+
namespace: envoy-gateway
22+
name: gateway
23+
spec:
24+
gatewayClassName: envoy-gateway-class
25+
listeners:
26+
- name: http-1
27+
protocol: HTTP
28+
port: 80
29+
allowedRoutes:
30+
namespaces:
31+
from: Same
32+
- name: http-2
33+
protocol: HTTP
34+
port: 8080
35+
allowedRoutes:
36+
namespaces:
37+
from: Same
38+
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
clientTrafficPolicies:
2+
- apiVersion: gateway.envoyproxy.io/v1alpha1
3+
kind: ClientTrafficPolicy
4+
metadata:
5+
creationTimestamp: null
6+
name: target-gateway
7+
namespace: envoy-gateway
8+
spec:
9+
targetRef:
10+
group: gateway.networking.k8s.io
11+
kind: Gateway
12+
name: gateway
13+
sectionName: http-1
14+
timeout:
15+
http:
16+
requestReceivedTimeout: 5s
17+
streamIdleTimeout: 1h
18+
status:
19+
ancestors:
20+
- ancestorRef:
21+
group: gateway.networking.k8s.io
22+
kind: Gateway
23+
name: gateway
24+
namespace: envoy-gateway
25+
sectionName: http-1
26+
conditions:
27+
- lastTransitionTime: null
28+
message: Policy has been accepted.
29+
reason: Accepted
30+
status: "True"
31+
type: Accepted
32+
controllerName: gateway.envoyproxy.io/gatewayclass-controller
33+
gateways:
34+
- apiVersion: gateway.networking.k8s.io/v1
35+
kind: Gateway
36+
metadata:
37+
creationTimestamp: null
38+
name: gateway
39+
namespace: envoy-gateway
40+
spec:
41+
gatewayClassName: envoy-gateway-class
42+
listeners:
43+
- allowedRoutes:
44+
namespaces:
45+
from: Same
46+
name: http-1
47+
port: 80
48+
protocol: HTTP
49+
- allowedRoutes:
50+
namespaces:
51+
from: Same
52+
name: http-2
53+
port: 8080
54+
protocol: HTTP
55+
status:
56+
listeners:
57+
- attachedRoutes: 0
58+
conditions:
59+
- lastTransitionTime: null
60+
message: Sending translated listener configuration to the data plane
61+
reason: Programmed
62+
status: "True"
63+
type: Programmed
64+
- lastTransitionTime: null
65+
message: Listener has been successfully translated
66+
reason: Accepted
67+
status: "True"
68+
type: Accepted
69+
- lastTransitionTime: null
70+
message: Listener references have been resolved
71+
reason: ResolvedRefs
72+
status: "True"
73+
type: ResolvedRefs
74+
name: http-1
75+
supportedKinds:
76+
- group: gateway.networking.k8s.io
77+
kind: HTTPRoute
78+
- group: gateway.networking.k8s.io
79+
kind: GRPCRoute
80+
- attachedRoutes: 0
81+
conditions:
82+
- lastTransitionTime: null
83+
message: Sending translated listener configuration to the data plane
84+
reason: Programmed
85+
status: "True"
86+
type: Programmed
87+
- lastTransitionTime: null
88+
message: Listener has been successfully translated
89+
reason: Accepted
90+
status: "True"
91+
type: Accepted
92+
- lastTransitionTime: null
93+
message: Listener references have been resolved
94+
reason: ResolvedRefs
95+
status: "True"
96+
type: ResolvedRefs
97+
name: http-2
98+
supportedKinds:
99+
- group: gateway.networking.k8s.io
100+
kind: HTTPRoute
101+
- group: gateway.networking.k8s.io
102+
kind: GRPCRoute
103+
infraIR:
104+
envoy-gateway/gateway:
105+
proxy:
106+
listeners:
107+
- address: null
108+
name: envoy-gateway/gateway/http-1
109+
ports:
110+
- containerPort: 10080
111+
name: http-80
112+
protocol: HTTP
113+
servicePort: 80
114+
- address: null
115+
name: envoy-gateway/gateway/http-2
116+
ports:
117+
- containerPort: 8080
118+
name: http-8080
119+
protocol: HTTP
120+
servicePort: 8080
121+
metadata:
122+
labels:
123+
gateway.envoyproxy.io/owning-gateway-name: gateway
124+
gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway
125+
ownerReference:
126+
kind: GatewayClass
127+
name: envoy-gateway-class
128+
name: envoy-gateway/gateway
129+
namespace: envoy-gateway-system
130+
xdsIR:
131+
envoy-gateway/gateway:
132+
accessLog:
133+
json:
134+
- path: /dev/stdout
135+
http:
136+
- address: 0.0.0.0
137+
hostnames:
138+
- '*'
139+
isHTTP2: false
140+
metadata:
141+
kind: Gateway
142+
name: gateway
143+
namespace: envoy-gateway
144+
sectionName: http-1
145+
name: envoy-gateway/gateway/http-1
146+
path:
147+
escapedSlashesAction: UnescapeAndRedirect
148+
mergeSlashes: true
149+
port: 10080
150+
timeout:
151+
http:
152+
requestReceivedTimeout: 5s
153+
streamIdleTimeout: 1h
154+
- address: 0.0.0.0
155+
hostnames:
156+
- '*'
157+
isHTTP2: false
158+
metadata:
159+
kind: Gateway
160+
name: gateway
161+
namespace: envoy-gateway
162+
sectionName: http-2
163+
name: envoy-gateway/gateway/http-2
164+
path:
165+
escapedSlashesAction: UnescapeAndRedirect
166+
mergeSlashes: true
167+
port: 8080
168+
readyListener:
169+
address: 0.0.0.0
170+
ipFamily: IPv4
171+
path: /ready
172+
port: 19003

internal/ir/xds.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,12 @@ type HTTPClientTimeout struct {
740740
RequestReceivedTimeout *metav1.Duration `json:"requestReceivedTimeout,omitempty" yaml:"requestReceivedTimeout,omitempty"`
741741
// IdleTimeout for an HTTP connection. Idle time is defined as a period in which there are no active requests in the connection.
742742
IdleTimeout *metav1.Duration `json:"idleTimeout,omitempty" yaml:"idleTimeout,omitempty"`
743+
// The stream idle timeout for connections managed by the connection manager.
744+
// If not specified, this defaults to 5 minutes. The default value was selected
745+
// so as not to interfere with any smaller configured timeouts that may have
746+
// existed in configurations prior to the introduction of this feature, while
747+
// introducing robustness to TCP connections that terminate without a FIN.
748+
StreamIdleTimeout *metav1.Duration `json:"streamIdleTimeout,omitempty" yaml:"streamIdleTimeout,omitempty"`
743749
}
744750

745751
// HTTPRoute holds the route information associated with the HTTP Route

internal/xds/translator/listener.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,10 @@ func (t *Translator) addHCMToXDSListener(xdsListener *listenerv3.Listener, irLis
382382
if irListener.Timeout.HTTP.IdleTimeout != nil {
383383
mgr.CommonHttpProtocolOptions.IdleTimeout = durationpb.New(irListener.Timeout.HTTP.IdleTimeout.Duration)
384384
}
385+
386+
if irListener.Timeout.HTTP.StreamIdleTimeout != nil {
387+
mgr.StreamIdleTimeout = durationpb.New(irListener.Timeout.HTTP.StreamIdleTimeout.Duration)
388+
}
385389
}
386390

387391
// Add the proxy protocol filter if needed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
http:
2+
- name: "first-listener"
3+
address: "::"
4+
port: 10080
5+
hostnames:
6+
- "*"
7+
path:
8+
mergeSlashes: true
9+
escapedSlashesAction: UnescapeAndRedirect
10+
routes:
11+
- name: "first-route"
12+
hostname: "*"
13+
destination:
14+
name: "first-route-dest"
15+
settings:
16+
- endpoints:
17+
- host: "1.2.3.4"
18+
port: 50000
19+
name: "first-route-dest/backend/0"
20+
timeout:
21+
http:
22+
requestReceivedTimeout: "5s"
23+
idleTimeout: "10s"
24+
streamIdleTimeout: "1h"
25+
tcp:
26+
- name: "second-listener"
27+
address: "::"
28+
port: 10081
29+
routes:
30+
- name: "second-route"
31+
destination:
32+
name: "second-route-dest"
33+
settings:
34+
- endpoints:
35+
- host: "1.2.3.4"
36+
port: 50000
37+
name: "second-route-dest/backend/0"
38+
timeout:
39+
tcp:
40+
idleTimeout: "1200s"
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
- circuitBreakers:
2+
thresholds:
3+
- maxRetries: 1024
4+
commonLbConfig: {}
5+
connectTimeout: 10s
6+
dnsLookupFamily: V4_PREFERRED
7+
edsClusterConfig:
8+
edsConfig:
9+
ads: {}
10+
resourceApiVersion: V3
11+
serviceName: first-route-dest
12+
ignoreHealthOnHostRemoval: true
13+
lbPolicy: LEAST_REQUEST
14+
loadBalancingPolicy:
15+
policies:
16+
- typedExtensionConfig:
17+
name: envoy.load_balancing_policies.least_request
18+
typedConfig:
19+
'@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest
20+
localityLbConfig:
21+
localityWeightedLbConfig: {}
22+
name: first-route-dest
23+
perConnectionBufferLimitBytes: 32768
24+
type: EDS
25+
- circuitBreakers:
26+
thresholds:
27+
- maxRetries: 1024
28+
commonLbConfig: {}
29+
connectTimeout: 10s
30+
dnsLookupFamily: V4_PREFERRED
31+
edsClusterConfig:
32+
edsConfig:
33+
ads: {}
34+
resourceApiVersion: V3
35+
serviceName: second-route-dest
36+
ignoreHealthOnHostRemoval: true
37+
lbPolicy: LEAST_REQUEST
38+
loadBalancingPolicy:
39+
policies:
40+
- typedExtensionConfig:
41+
name: envoy.load_balancing_policies.least_request
42+
typedConfig:
43+
'@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest
44+
localityLbConfig:
45+
localityWeightedLbConfig: {}
46+
name: second-route-dest
47+
perConnectionBufferLimitBytes: 32768
48+
type: EDS
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
- clusterName: first-route-dest
2+
endpoints:
3+
- lbEndpoints:
4+
- endpoint:
5+
address:
6+
socketAddress:
7+
address: 1.2.3.4
8+
portValue: 50000
9+
loadBalancingWeight: 1
10+
loadBalancingWeight: 1
11+
locality:
12+
region: first-route-dest/backend/0
13+
- clusterName: second-route-dest
14+
endpoints:
15+
- lbEndpoints:
16+
- endpoint:
17+
address:
18+
socketAddress:
19+
address: 1.2.3.4
20+
portValue: 50000
21+
loadBalancingWeight: 1
22+
loadBalancingWeight: 1
23+
locality:
24+
region: second-route-dest/backend/0

0 commit comments

Comments
 (0)