Skip to content

Commit 0a049f4

Browse files
committed
Introduce HTTP2 health check transport options
Signed-off-by: Dani Louca <[email protected]>
1 parent bdeee09 commit 0a049f4

File tree

4 files changed

+104
-27
lines changed

4 files changed

+104
-27
lines changed

.chloggen/http2ping.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: enhancement
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver)
7+
component: config/confighttp
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Exposes http/2 transport settings to enable health check and workaround golang http/2 issue https://github.com/golang/go/issues/59690
11+
12+
# One or more tracking issues or pull requests related to the change
13+
issues: [9022]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# Optional: The change log or logs in which this entry should be included.
21+
# e.g. '[user]' or '[user, api]'
22+
# Include 'user' if the change is relevant to end users.
23+
# Include 'api' if there is a change to a library API.
24+
# Default: '[user]'
25+
change_logs: []

config/confighttp/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ README](../configtls/README.md).
2929
- [`idle_conn_timeout`](https://golang.org/pkg/net/http/#Transport)
3030
- [`auth`](../configauth/README.md)
3131
- [`disable_keep_alives`](https://golang.org/pkg/net/http/#Transport)
32+
- [`http2_read_idle_timeout`](https://pkg.go.dev/golang.org/x/net/http2#Transport)
33+
- [`http2_ping_timeout`](https://pkg.go.dev/golang.org/x/net/http2#Transport)
3234

3335
Example:
3436

config/confighttp/confighttp.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package confighttp // import "go.opentelemetry.io/collector/config/confighttp"
66
import (
77
"crypto/tls"
88
"errors"
9+
"fmt"
910
"io"
1011
"net"
1112
"net/http"
@@ -86,6 +87,16 @@ type HTTPClientSettings struct {
8687
// connection for every request. Before enabling this option please consider whether changes
8788
// to idle connection settings can achieve your goal.
8889
DisableKeepAlives bool `mapstructure:"disable_keep_alives"`
90+
91+
// This is needed in case you run into
92+
// https://github.com/golang/go/issues/59690
93+
// https://github.com/golang/go/issues/36026
94+
// HTTP2ReadIdleTimeout if the connection has been idle for the configured value send a ping frame for health check
95+
// 0s means no health check will be performed.
96+
HTTP2ReadIdleTimeout *time.Duration `mapstructure:"http2_read_idle_timeout"`
97+
// HTTP2PingTimeout if there's no response to the ping within the configured value, the connection will be closed.
98+
// Defaults to 15s.
99+
HTTP2PingTimeout *time.Duration `mapstructure:"http2_ping_timeout"`
89100
}
90101

91102
// NewDefaultHTTPClientSettings returns HTTPClientSettings type object with
@@ -147,6 +158,17 @@ func (hcs *HTTPClientSettings) ToClient(host component.Host, settings component.
147158

148159
transport.DisableKeepAlives = hcs.DisableKeepAlives
149160

161+
if hcs.HTTP2ReadIdleTimeout != nil && hcs.HTTP2ReadIdleTimeout.Seconds() > 0 {
162+
transport2, transportErr := http2.ConfigureTransports(transport)
163+
if transportErr != nil {
164+
return nil, fmt.Errorf("failed to configure http2 transport: %w", transportErr)
165+
}
166+
transport2.ReadIdleTimeout = *hcs.HTTP2ReadIdleTimeout
167+
if hcs.HTTP2PingTimeout != nil {
168+
transport2.PingTimeout = *hcs.HTTP2PingTimeout
169+
}
170+
}
171+
150172
clientTransport := (http.RoundTripper)(transport)
151173

152174
// The Auth RoundTripper should always be the innermost to ensure that

config/confighttp/confighttp_test.go

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ func TestAllHTTPClientSettings(t *testing.T) {
5353
maxIdleConnsPerHost := 40
5454
maxConnsPerHost := 45
5555
idleConnTimeout := 30 * time.Second
56+
http2PingTimeout := 5 * time.Second
5657
tests := []struct {
5758
name string
5859
settings HTTPClientSettings
@@ -65,15 +66,17 @@ func TestAllHTTPClientSettings(t *testing.T) {
6566
TLSSetting: configtls.TLSClientSetting{
6667
Insecure: false,
6768
},
68-
ReadBufferSize: 1024,
69-
WriteBufferSize: 512,
70-
MaxIdleConns: &maxIdleConns,
71-
MaxIdleConnsPerHost: &maxIdleConnsPerHost,
72-
MaxConnsPerHost: &maxConnsPerHost,
73-
IdleConnTimeout: &idleConnTimeout,
74-
CustomRoundTripper: func(next http.RoundTripper) (http.RoundTripper, error) { return next, nil },
75-
Compression: "",
76-
DisableKeepAlives: true,
69+
ReadBufferSize: 1024,
70+
WriteBufferSize: 512,
71+
MaxIdleConns: &maxIdleConns,
72+
MaxIdleConnsPerHost: &maxIdleConnsPerHost,
73+
MaxConnsPerHost: &maxConnsPerHost,
74+
IdleConnTimeout: &idleConnTimeout,
75+
CustomRoundTripper: func(next http.RoundTripper) (http.RoundTripper, error) { return next, nil },
76+
Compression: "",
77+
DisableKeepAlives: true,
78+
HTTP2ReadIdleTimeout: &idleConnTimeout,
79+
HTTP2PingTimeout: &http2PingTimeout,
7780
},
7881
shouldError: false,
7982
},
@@ -84,15 +87,17 @@ func TestAllHTTPClientSettings(t *testing.T) {
8487
TLSSetting: configtls.TLSClientSetting{
8588
Insecure: false,
8689
},
87-
ReadBufferSize: 1024,
88-
WriteBufferSize: 512,
89-
MaxIdleConns: &maxIdleConns,
90-
MaxIdleConnsPerHost: &maxIdleConnsPerHost,
91-
MaxConnsPerHost: &maxConnsPerHost,
92-
IdleConnTimeout: &idleConnTimeout,
93-
CustomRoundTripper: func(next http.RoundTripper) (http.RoundTripper, error) { return next, nil },
94-
Compression: "none",
95-
DisableKeepAlives: true,
90+
ReadBufferSize: 1024,
91+
WriteBufferSize: 512,
92+
MaxIdleConns: &maxIdleConns,
93+
MaxIdleConnsPerHost: &maxIdleConnsPerHost,
94+
MaxConnsPerHost: &maxConnsPerHost,
95+
IdleConnTimeout: &idleConnTimeout,
96+
CustomRoundTripper: func(next http.RoundTripper) (http.RoundTripper, error) { return next, nil },
97+
Compression: "none",
98+
DisableKeepAlives: true,
99+
HTTP2ReadIdleTimeout: &idleConnTimeout,
100+
HTTP2PingTimeout: &http2PingTimeout,
96101
},
97102
shouldError: false,
98103
},
@@ -103,15 +108,38 @@ func TestAllHTTPClientSettings(t *testing.T) {
103108
TLSSetting: configtls.TLSClientSetting{
104109
Insecure: false,
105110
},
106-
ReadBufferSize: 1024,
107-
WriteBufferSize: 512,
108-
MaxIdleConns: &maxIdleConns,
109-
MaxIdleConnsPerHost: &maxIdleConnsPerHost,
110-
MaxConnsPerHost: &maxConnsPerHost,
111-
IdleConnTimeout: &idleConnTimeout,
112-
CustomRoundTripper: func(next http.RoundTripper) (http.RoundTripper, error) { return next, nil },
113-
Compression: "gzip",
114-
DisableKeepAlives: true,
111+
ReadBufferSize: 1024,
112+
WriteBufferSize: 512,
113+
MaxIdleConns: &maxIdleConns,
114+
MaxIdleConnsPerHost: &maxIdleConnsPerHost,
115+
MaxConnsPerHost: &maxConnsPerHost,
116+
IdleConnTimeout: &idleConnTimeout,
117+
CustomRoundTripper: func(next http.RoundTripper) (http.RoundTripper, error) { return next, nil },
118+
Compression: "gzip",
119+
DisableKeepAlives: true,
120+
HTTP2ReadIdleTimeout: &idleConnTimeout,
121+
HTTP2PingTimeout: &http2PingTimeout,
122+
},
123+
shouldError: false,
124+
},
125+
{
126+
name: "all_valid_settings_http2_health_check",
127+
settings: HTTPClientSettings{
128+
Endpoint: "localhost:1234",
129+
TLSSetting: configtls.TLSClientSetting{
130+
Insecure: false,
131+
},
132+
ReadBufferSize: 1024,
133+
WriteBufferSize: 512,
134+
MaxIdleConns: &maxIdleConns,
135+
MaxIdleConnsPerHost: &maxIdleConnsPerHost,
136+
MaxConnsPerHost: &maxConnsPerHost,
137+
IdleConnTimeout: &idleConnTimeout,
138+
CustomRoundTripper: func(next http.RoundTripper) (http.RoundTripper, error) { return next, nil },
139+
Compression: "gzip",
140+
DisableKeepAlives: true,
141+
HTTP2ReadIdleTimeout: &idleConnTimeout,
142+
HTTP2PingTimeout: &http2PingTimeout,
115143
},
116144
shouldError: false,
117145
},

0 commit comments

Comments
 (0)