Skip to content

Commit

Permalink
reverseproxy: Adjust defaults, document defaults
Browse files Browse the repository at this point in the history
Related to some of the issues in #4245, a complaint about the proxy transport defaults not being properly documented in https://caddy.community/t/default-values-for-directives/14254/6.

- Dug into the stdlib to find the actual defaults for some of the timeouts and buffer limits, documenting them in godoc so the JSON docs get them next release.

- Moved the keep-alive and dial-timeout defaults from `reverseproxy.go` to `httptransport.go`. It doesn't make sense to set defaults in the proxy, because then any time the transport is configured with non-defaults, the keep-alive and dial-timeout defaults are lost!

- Sped up the dial timeout from 10s to 3s, in practice it rarely makes sense to wait a whole 10s for dialing. A shorter timeout helps a lot with the load balancer retries, so using something lower helps with user experience.
  • Loading branch information
francislavoie committed Nov 24, 2021
1 parent 789efa5 commit d6d1ef0
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 18 deletions.
35 changes: 25 additions & 10 deletions modules/caddyhttp/reverseproxy/httptransport.go
Expand Up @@ -63,28 +63,28 @@ type HTTPTransport struct {
MaxConnsPerHost int `json:"max_conns_per_host,omitempty"`

// How long to wait before timing out trying to connect to
// an upstream.
// an upstream. Default: `3s`.
DialTimeout caddy.Duration `json:"dial_timeout,omitempty"`

// How long to wait before spawning an RFC 6555 Fast Fallback
// connection. A negative value disables this.
// connection. A negative value disables this. Default: `300ms`.
FallbackDelay caddy.Duration `json:"dial_fallback_delay,omitempty"`

// How long to wait for reading response headers from server.
// How long to wait for reading response headers from server. Default: No timeout.
ResponseHeaderTimeout caddy.Duration `json:"response_header_timeout,omitempty"`

// The length of time to wait for a server's first response
// headers after fully writing the request headers if the
// request has a header "Expect: 100-continue".
// request has a header "Expect: 100-continue". Default: No timeout.
ExpectContinueTimeout caddy.Duration `json:"expect_continue_timeout,omitempty"`

// The maximum bytes to read from response headers.
// The maximum bytes to read from response headers. Default: `10MiB`.
MaxResponseHeaderSize int64 `json:"max_response_header_size,omitempty"`

// The size of the write buffer in bytes.
// The size of the write buffer in bytes. Default: `4KiB`.
WriteBufferSize int `json:"write_buffer_size,omitempty"`

// The size of the read buffer in bytes.
// The size of the read buffer in bytes. Default: `4KiB`.
ReadBufferSize int `json:"read_buffer_size,omitempty"`

// The versions of HTTP to support. As a special case, "h2c"
Expand Down Expand Up @@ -147,6 +147,21 @@ func (h *HTTPTransport) Provision(ctx caddy.Context) error {

// NewTransport builds a standard-lib-compatible http.Transport value from h.
func (h *HTTPTransport) NewTransport(ctx caddy.Context) (*http.Transport, error) {
// Set keep-alive defaults if it wasn't otherwise configured
if h.KeepAlive == nil {
h.KeepAlive = &KeepAlive{
ProbeInterval: caddy.Duration(30 * time.Second),
IdleConnTimeout: caddy.Duration(2 * time.Minute),
MaxIdleConnsPerHost: 32, // seems about optimal, see #2805
}
}

// Set a relatively short default dial timeout.
// This is helpful to make load-balancer retries more speedy.
if h.DialTimeout == 0 {
h.DialTimeout = caddy.Duration(3 * time.Second)
}

dialer := &net.Dialer{
Timeout: time.Duration(h.DialTimeout),
FallbackDelay: time.Duration(h.FallbackDelay),
Expand Down Expand Up @@ -303,7 +318,7 @@ type TLSConfig struct {
// option except in testing or local development environments.
InsecureSkipVerify bool `json:"insecure_skip_verify,omitempty"`

// The duration to allow a TLS handshake to a server.
// The duration to allow a TLS handshake to a server. Default: No timeout.
HandshakeTimeout caddy.Duration `json:"handshake_timeout,omitempty"`

// The server name (SNI) to use in TLS handshakes.
Expand Down Expand Up @@ -405,7 +420,7 @@ type KeepAlive struct {
// Whether HTTP Keep-Alive is enabled. Default: true
Enabled *bool `json:"enabled,omitempty"`

// How often to probe for liveness.
// How often to probe for liveness. Default: `30s`.
ProbeInterval caddy.Duration `json:"probe_interval,omitempty"`

// Maximum number of idle connections. Default: 0, which means no limit.
Expand All @@ -414,7 +429,7 @@ type KeepAlive struct {
// Maximum number of idle connections per host. Default: 32.
MaxIdleConnsPerHost int `json:"max_idle_conns_per_host,omitempty"`

// How long connections should be kept alive when idle. Default: 0, which means no timeout.
// How long connections should be kept alive when idle. Default: `2m`.
IdleConnTimeout caddy.Duration `json:"idle_timeout,omitempty"`
}

Expand Down
9 changes: 1 addition & 8 deletions modules/caddyhttp/reverseproxy/reverseproxy.go
Expand Up @@ -204,14 +204,7 @@ func (h *Handler) Provision(ctx caddy.Context) error {

// set up transport
if h.Transport == nil {
t := &HTTPTransport{
KeepAlive: &KeepAlive{
ProbeInterval: caddy.Duration(30 * time.Second),
IdleConnTimeout: caddy.Duration(2 * time.Minute),
MaxIdleConnsPerHost: 32, // seems about optimal, see #2805
},
DialTimeout: caddy.Duration(10 * time.Second),
}
t := &HTTPTransport{}
err := t.Provision(ctx)
if err != nil {
return fmt.Errorf("provisioning default transport: %v", err)
Expand Down

0 comments on commit d6d1ef0

Please sign in to comment.