Add health check timeout parameter

This commit is contained in:
Jared Biel 2018-09-27 13:16:03 -05:00 committed by Traefiker Bot
parent f10516deb7
commit 5acd43efaf
45 changed files with 189 additions and 28 deletions

View file

@ -88,6 +88,7 @@ var _templatesConsul_catalogTmpl = []byte(`[backends]
path = "{{ $healthCheck.Path }}" path = "{{ $healthCheck.Path }}"
port = {{ $healthCheck.Port }} port = {{ $healthCheck.Port }}
interval = "{{ $healthCheck.Interval }}" interval = "{{ $healthCheck.Interval }}"
timeout = "{{ $healthCheck.Timeout }}"
hostname = "{{ $healthCheck.Hostname }}" hostname = "{{ $healthCheck.Hostname }}"
{{if $healthCheck.Headers }} {{if $healthCheck.Headers }}
[backends."backend-{{ $backendName }}".healthCheck.headers] [backends."backend-{{ $backendName }}".healthCheck.headers]
@ -356,6 +357,7 @@ var _templatesDockerTmpl = []byte(`{{$backendServers := .Servers}}
path = "{{ $healthCheck.Path }}" path = "{{ $healthCheck.Path }}"
port = {{ $healthCheck.Port }} port = {{ $healthCheck.Port }}
interval = "{{ $healthCheck.Interval }}" interval = "{{ $healthCheck.Interval }}"
timeout = "{{ $healthCheck.Timeout }}"
hostname = "{{ $healthCheck.Hostname }}" hostname = "{{ $healthCheck.Hostname }}"
{{if $healthCheck.Headers }} {{if $healthCheck.Headers }}
[backends."backend-{{ $backendName }}".healthCheck.headers] [backends."backend-{{ $backendName }}".healthCheck.headers]
@ -624,6 +626,7 @@ var _templatesEcsTmpl = []byte(`[backends]
path = "{{ $healthCheck.Path }}" path = "{{ $healthCheck.Path }}"
port = {{ $healthCheck.Port }} port = {{ $healthCheck.Port }}
interval = "{{ $healthCheck.Interval }}" interval = "{{ $healthCheck.Interval }}"
timeout = "{{ $healthCheck.Timeout }}"
hostname = "{{ $healthCheck.Hostname }}" hostname = "{{ $healthCheck.Hostname }}"
{{if $healthCheck.Headers }} {{if $healthCheck.Headers }}
[backends."backend-{{ $serviceName }}".healthCheck.headers] [backends."backend-{{ $serviceName }}".healthCheck.headers]
@ -1152,6 +1155,7 @@ var _templatesKvTmpl = []byte(`[backends]
path = "{{ $healthCheck.Path }}" path = "{{ $healthCheck.Path }}"
port = {{ $healthCheck.Port }} port = {{ $healthCheck.Port }}
interval = "{{ $healthCheck.Interval }}" interval = "{{ $healthCheck.Interval }}"
timeout = "{{ $healthCheck.Timeout }}"
hostname = "{{ $healthCheck.Hostname }}" hostname = "{{ $healthCheck.Hostname }}"
{{if $healthCheck.Headers }} {{if $healthCheck.Headers }}
[backends."{{ $backendName }}".healthCheck.headers] [backends."{{ $backendName }}".healthCheck.headers]
@ -1437,6 +1441,7 @@ var _templatesMarathonTmpl = []byte(`{{ $apps := .Applications }}
path = "{{ $healthCheck.Path }}" path = "{{ $healthCheck.Path }}"
port = {{ $healthCheck.Port }} port = {{ $healthCheck.Port }}
interval = "{{ $healthCheck.Interval }}" interval = "{{ $healthCheck.Interval }}"
timeout = "{{ $healthCheck.Timeout }}"
hostname = "{{ $healthCheck.Hostname }}" hostname = "{{ $healthCheck.Hostname }}"
{{if $healthCheck.Headers }} {{if $healthCheck.Headers }}
[backends.{{ $backendName }}.healthCheck.headers] [backends.{{ $backendName }}.healthCheck.headers]
@ -1707,6 +1712,7 @@ var _templatesMesosTmpl = []byte(`[backends]
path = "{{ $healthCheck.Path }}" path = "{{ $healthCheck.Path }}"
port = {{ $healthCheck.Port }} port = {{ $healthCheck.Port }}
interval = "{{ $healthCheck.Interval }}" interval = "{{ $healthCheck.Interval }}"
timeout = "{{ $healthCheck.Timeout }}"
hostname = "{{ $healthCheck.Hostname }}" hostname = "{{ $healthCheck.Hostname }}"
{{if $healthCheck.Headers }} {{if $healthCheck.Headers }}
[backends."backend-{{ $backendName }}".healthCheck.headers] [backends."backend-{{ $backendName }}".healthCheck.headers]
@ -2000,6 +2006,7 @@ var _templatesRancherTmpl = []byte(`{{ $backendServers := .Backends }}
path = "{{ $healthCheck.Path }}" path = "{{ $healthCheck.Path }}"
port = {{ $healthCheck.Port }} port = {{ $healthCheck.Port }}
interval = "{{ $healthCheck.Interval }}" interval = "{{ $healthCheck.Interval }}"
timeout = "{{ $healthCheck.Timeout }}"
hostname = "{{ $healthCheck.Hostname }}" hostname = "{{ $healthCheck.Hostname }}"
{{if $healthCheck.Headers }} {{if $healthCheck.Headers }}
[backends."backend-{{ $backendName }}".healthCheck.headers] [backends."backend-{{ $backendName }}".healthCheck.headers]

View file

@ -177,6 +177,7 @@ func NewTraefikDefaultPointersConfiguration() *TraefikConfiguration {
// default HealthCheckConfig // default HealthCheckConfig
healthCheck := configuration.HealthCheckConfig{ healthCheck := configuration.HealthCheckConfig{
Interval: parse.Duration(configuration.DefaultHealthCheckInterval), Interval: parse.Duration(configuration.DefaultHealthCheckInterval),
Timeout: parse.Duration(configuration.DefaultHealthCheckTimeout),
} }
// default RespondingTimeouts // default RespondingTimeouts
@ -302,6 +303,7 @@ func NewTraefikConfiguration() *TraefikConfiguration {
MaxIdleConnsPerHost: 200, MaxIdleConnsPerHost: 200,
HealthCheck: &configuration.HealthCheckConfig{ HealthCheck: &configuration.HealthCheckConfig{
Interval: parse.Duration(configuration.DefaultHealthCheckInterval), Interval: parse.Duration(configuration.DefaultHealthCheckInterval),
Timeout: parse.Duration(configuration.DefaultHealthCheckTimeout),
}, },
LifeCycle: &configuration.LifeCycle{ LifeCycle: &configuration.LifeCycle{
GraceTimeOut: parse.Duration(configuration.DefaultGraceTimeout), GraceTimeOut: parse.Duration(configuration.DefaultGraceTimeout),

View file

@ -42,6 +42,9 @@ const (
// DefaultHealthCheckInterval is the default health check interval. // DefaultHealthCheckInterval is the default health check interval.
DefaultHealthCheckInterval = 30 * time.Second DefaultHealthCheckInterval = 30 * time.Second
// DefaultHealthCheckTimeout is the default health check request timeout.
DefaultHealthCheckTimeout = 5 * time.Second
// DefaultDialTimeout when connecting to a backend server. // DefaultDialTimeout when connecting to a backend server.
DefaultDialTimeout = 30 * time.Second DefaultDialTimeout = 30 * time.Second
@ -372,6 +375,7 @@ type Retry struct {
// HealthCheckConfig contains health check configuration parameters. // HealthCheckConfig contains health check configuration parameters.
type HealthCheckConfig struct { type HealthCheckConfig struct {
Interval parse.Duration `description:"Default periodicity of enabled health checks" export:"true"` Interval parse.Duration `description:"Default periodicity of enabled health checks" export:"true"`
Timeout parse.Duration `description:"Default request timeout of enabled health checks" export:"true"`
} }
// RespondingTimeouts contains timeout configurations for incoming requests to the Traefik instance. // RespondingTimeouts contains timeout configurations for incoming requests to the Traefik instance.

View file

@ -452,9 +452,11 @@ If not, a new backend will be assigned.
#### Health Check #### Health Check
A health check can be configured in order to remove a backend from LB rotation as long as it keeps returning HTTP status codes other than `2xx` or `3xx` to HTTP GET requests periodically carried out by Traefik. A health check can be configured in order to remove a backend from LB rotation as long as it keeps returning HTTP status codes other than `2xx` or `3xx` to HTTP GET requests periodically carried out by Traefik.
The check is defined by a path appended to the backend URL and an interval (given in a format understood by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration)) specifying how often the health check should be executed (the default being 30 seconds). The check is defined by a path appended to the backend URL and an interval specifying how often the health check should be executed (the default being 30 seconds.)
Each backend must respond to the health check within 5 seconds. Each backend must respond to the health check within a timeout duration (the default being 5 seconds.)
Interval and timeout are to be given in a format understood by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration).
The interval must be greater than the timeout. If configuration doesn't reflect this, the interval will be set to timeout + 1 second.
By default, the port of the backend server is used, however, this may be overridden. By default, the port of the backend server is used, however, this may be overridden.
A recovering backend returning `2xx` or `3xx` responses again is being returned to the LB rotation pool. A recovering backend returning `2xx` or `3xx` responses again is being returned to the LB rotation pool.
@ -466,6 +468,7 @@ For example:
[backends.backend1.healthcheck] [backends.backend1.healthcheck]
path = "/health" path = "/health"
interval = "10s" interval = "10s"
timeout = "3s"
``` ```
To use a different port for the health check: To use a different port for the health check:
@ -475,6 +478,7 @@ To use a different port for the health check:
[backends.backend1.healthcheck] [backends.backend1.healthcheck]
path = "/health" path = "/health"
interval = "10s" interval = "10s"
timeout = "3s"
port = 8080 port = 8080
``` ```
@ -486,6 +490,7 @@ To use a different scheme for the health check:
[backends.backend1.healthcheck] [backends.backend1.healthcheck]
path = "/health" path = "/health"
interval = "10s" interval = "10s"
timeout = "3s"
scheme = "http" scheme = "http"
``` ```
@ -496,6 +501,7 @@ Additional http headers and hostname to health check request can be specified, f
[backends.backend1.healthcheck] [backends.backend1.healthcheck]
path = "/health" path = "/health"
interval = "10s" interval = "10s"
timeout = "3s"
hostname = "myhost.com" hostname = "myhost.com"
port = 8080 port = 8080
[backends.backend1.healthcheck.headers] [backends.backend1.healthcheck.headers]

View file

@ -106,7 +106,8 @@ Additional settings can be defined using Consul Catalog tags.
| `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. | | `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. |
| `<prefix>.backend.circuitbreaker.expression=EXPR` | Creates a [circuit breaker](/basics/#backends) to be used against the backend. ex: `NetworkErrorRatio() > 0.` | | `<prefix>.backend.circuitbreaker.expression=EXPR` | Creates a [circuit breaker](/basics/#backends) to be used against the backend. ex: `NetworkErrorRatio() > 0.` |
| `<prefix>.backend.healthcheck.path=/health` | Enables health check for the backend, hitting the container at `path`. | | `<prefix>.backend.healthcheck.path=/health` | Enables health check for the backend, hitting the container at `path`. |
| `<prefix>.backend.healthcheck.interval=1s` | Defines the health check interval. | | `<prefix>.backend.healthcheck.interval=5s` | Defines the health check interval. |
| `<prefix>.backend.healthcheck.timeout=3s` | Defines the health check request timeout |
| `<prefix>.backend.healthcheck.port=8080` | Sets a different port for the health check. | | `<prefix>.backend.healthcheck.port=8080` | Sets a different port for the health check. |
| `traefik.backend.healthcheck.scheme=http` | Overrides the server URL scheme. | | `traefik.backend.healthcheck.scheme=http` | Overrides the server URL scheme. |
| `<prefix>.backend.healthcheck.hostname=foobar.com` | Defines the health check hostname. | | `<prefix>.backend.healthcheck.hostname=foobar.com` | Defines the health check hostname. |

View file

@ -223,7 +223,8 @@ Labels can be used on containers to override default behavior.
| `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. | | `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. |
| `traefik.backend.circuitbreaker.expression=EXPR` | Creates a [circuit breaker](/basics/#backends) to be used against the backend | | `traefik.backend.circuitbreaker.expression=EXPR` | Creates a [circuit breaker](/basics/#backends) to be used against the backend |
| `traefik.backend.healthcheck.path=/health` | Enables health check for the backend, hitting the container at `path`. | | `traefik.backend.healthcheck.path=/health` | Enables health check for the backend, hitting the container at `path`. |
| `traefik.backend.healthcheck.interval=1s` | Defines the health check interval. | | `traefik.backend.healthcheck.interval=5s` | Defines the health check interval. |
| `traefik.backend.healthcheck.timeout=3s` | Defines the health check request timeout. |
| `traefik.backend.healthcheck.port=8080` | Sets a different port for the health check. | | `traefik.backend.healthcheck.port=8080` | Sets a different port for the health check. |
| `traefik.backend.healthcheck.scheme=http` | Overrides the server URL scheme. | | `traefik.backend.healthcheck.scheme=http` | Overrides the server URL scheme. |
| `traefik.backend.healthcheck.hostname=foobar.com` | Defines the health check hostname. | | `traefik.backend.healthcheck.hostname=foobar.com` | Defines the health check hostname. |

View file

@ -145,7 +145,8 @@ Labels can be used on task containers to override default behavior:
| `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. | | `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. |
| `traefik.backend.circuitbreaker.expression=EXPR` | Creates a [circuit breaker](/basics/#backends) to be used against the backend | | `traefik.backend.circuitbreaker.expression=EXPR` | Creates a [circuit breaker](/basics/#backends) to be used against the backend |
| `traefik.backend.healthcheck.path=/health` | Enables health check for the backend, hitting the container at `path`. | | `traefik.backend.healthcheck.path=/health` | Enables health check for the backend, hitting the container at `path`. |
| `traefik.backend.healthcheck.interval=1s` | Defines the health check interval. (Default: 30s) | | `traefik.backend.healthcheck.interval=5s` | Defines the health check interval. (Default: 30s) |
| `traefik.backend.healthcheck.timeout=3s` | Defines the health check request timeout. (Default: 5s) |
| `traefik.backend.healthcheck.scheme=http` | Overrides the server URL scheme. | | `traefik.backend.healthcheck.scheme=http` | Overrides the server URL scheme. |
| `traefik.backend.healthcheck.port=8080` | Sets a different port for the health check. | | `traefik.backend.healthcheck.port=8080` | Sets a different port for the health check. |
| `traefik.backend.healthcheck.hostname=foobar.com` | Defines the health check hostname. | | `traefik.backend.healthcheck.hostname=foobar.com` | Defines the health check hostname. |

View file

@ -37,6 +37,7 @@ Træfik can be configured with a file.
path = "/health" path = "/health"
port = 88 port = 88
interval = "30s" interval = "30s"
timeout = "5s"
scheme = "http" scheme = "http"
hostname = "myhost.com" hostname = "myhost.com"
[backends.backend1.healthcheck.headers] [backends.backend1.healthcheck.headers]

View file

@ -209,7 +209,8 @@ The following labels can be defined on Marathon applications. They adjust the be
| `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. | | `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. |
| `traefik.backend.circuitbreaker.expression=EXPR` | Creates a [circuit breaker](/basics/#backends) to be used against the backend | | `traefik.backend.circuitbreaker.expression=EXPR` | Creates a [circuit breaker](/basics/#backends) to be used against the backend |
| `traefik.backend.healthcheck.path=/health` | Enables health check for the backend, hitting the container at `path`. | | `traefik.backend.healthcheck.path=/health` | Enables health check for the backend, hitting the container at `path`. |
| `traefik.backend.healthcheck.interval=1s` | Defines the health check interval. (Default: 30s) | | `traefik.backend.healthcheck.interval=5s` | Defines the health check interval. (Default: 30s) |
| `traefik.backend.healthcheck.timeout=3s` | Defines the health check request timeout. (Default: 5s) |
| `traefik.backend.healthcheck.port=8080` | Sets a different port for the health check. | | `traefik.backend.healthcheck.port=8080` | Sets a different port for the health check. |
| `traefik.backend.healthcheck.scheme=http` | Overrides the server URL scheme. | | `traefik.backend.healthcheck.scheme=http` | Overrides the server URL scheme. |
| `traefik.backend.healthcheck.hostname=foobar.com` | Defines the health check hostname. | | `traefik.backend.healthcheck.hostname=foobar.com` | Defines the health check hostname. |

View file

@ -123,7 +123,8 @@ The following labels can be defined on Mesos tasks. They adjust the behavior for
| `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. | | `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. |
| `traefik.backend.circuitbreaker.expression=EXPR` | Creates a [circuit breaker](/basics/#backends) to be used against the backend | | `traefik.backend.circuitbreaker.expression=EXPR` | Creates a [circuit breaker](/basics/#backends) to be used against the backend |
| `traefik.backend.healthcheck.path=/health` | Enables health check for the backend, hitting the container at `path`. | | `traefik.backend.healthcheck.path=/health` | Enables health check for the backend, hitting the container at `path`. |
| `traefik.backend.healthcheck.interval=1s` | Defines the health check interval. (Default: 30s) | | `traefik.backend.healthcheck.interval=5s` | Defines the health check interval. (Default: 30s) |
| `traefik.backend.healthcheck.timeout=3s` | Defines the health check request timeout. (Default: 5s) |
| `traefik.backend.healthcheck.scheme=http` | Overrides the server URL scheme. | | `traefik.backend.healthcheck.scheme=http` | Overrides the server URL scheme. |
| `traefik.backend.healthcheck.port=8080` | Sets a different port for the health check. | | `traefik.backend.healthcheck.port=8080` | Sets a different port for the health check. |
| `traefik.backend.healthcheck.hostname=foobar.com` | Defines the health check hostname. | | `traefik.backend.healthcheck.hostname=foobar.com` | Defines the health check hostname. |

View file

@ -153,7 +153,8 @@ Labels can be used on task containers to override default behavior:
| `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. | | `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. |
| `traefik.backend.circuitbreaker.expression=EXPR` | Creates a [circuit breaker](/basics/#backends) to be used against the backend | | `traefik.backend.circuitbreaker.expression=EXPR` | Creates a [circuit breaker](/basics/#backends) to be used against the backend |
| `traefik.backend.healthcheck.path=/health` | Enables health check for the backend, hitting the container at `path`. | | `traefik.backend.healthcheck.path=/health` | Enables health check for the backend, hitting the container at `path`. |
| `traefik.backend.healthcheck.interval=1s` | Defines the health check interval. | | `traefik.backend.healthcheck.interval=5s` | Defines the health check interval. |
| `traefik.backend.healthcheck.timeout=3s ` | Defines the health check request timeout. |
| `traefik.backend.healthcheck.port=8080` | Sets a different port for the health check. | | `traefik.backend.healthcheck.port=8080` | Sets a different port for the health check. |
| `traefik.backend.healthcheck.scheme=http` | Overrides the server URL scheme. | | `traefik.backend.healthcheck.scheme=http` | Overrides the server URL scheme. |
| `traefik.backend.healthcheck.hostname=foobar.com` | Defines the health check hostname. | | `traefik.backend.healthcheck.hostname=foobar.com` | Defines the health check hostname. |

View file

@ -103,7 +103,8 @@ Labels, set through extensions or the property manager, can be used on services
| `traefik.servicefabric.enablelabeloverrides` | Toggle whether labels can be overridden using the Service Fabric Property Manager API | | `traefik.servicefabric.enablelabeloverrides` | Toggle whether labels can be overridden using the Service Fabric Property Manager API |
| `traefik.backend.healthcheck.path=/health` | Enable health check for the backend, hitting the container at `path`. | | `traefik.backend.healthcheck.path=/health` | Enable health check for the backend, hitting the container at `path`. |
| `traefik.backend.healthcheck.port=8080` | Allow to use a different port for the health check. | | `traefik.backend.healthcheck.port=8080` | Allow to use a different port for the health check. |
| `traefik.backend.healthcheck.interval=1s` | Define the health check interval. | | `traefik.backend.healthcheck.interval=5s` | Define the health check interval. |
| `traefik.backend.healthcheck.timeout=3s` | Define the health check request timeout. |
| `traefik.backend.healthcheck.hostname=foobar.com` | Define the health check hostname. | | `traefik.backend.healthcheck.hostname=foobar.com` | Define the health check hostname. |
| `traefik.backend.healthcheck.headers=EXPR` | Define the health check request headers <br>Format: <code>HEADER:value&vert;&vert;HEADER2:value2</code> | | `traefik.backend.healthcheck.headers=EXPR` | Define the health check request headers <br>Format: <code>HEADER:value&vert;&vert;HEADER2:value2</code> |
| `traefik.backend.loadbalancer.method=drr` | Override the default `wrr` load balancer algorithm | | `traefik.backend.loadbalancer.method=drr` | Override the default `wrr` load balancer algorithm |

View file

@ -241,19 +241,23 @@ Example configuration:
# Enable custom health check options. # Enable custom health check options.
[healthcheck] [healthcheck]
# Set the default health check interval. # Set the default health check interval and timeout.
# #
# Optional # Optional
# Default: "30s" # Default: "30s"
# #
# interval = "30s" # interval = "30s"
# timeout = "5s"
``` ```
- `interval` set the default health check interval. - `interval` sets the default health check interval.
Will only be effective if health check paths are defined. - `timeout` sets the default health check request timeout.
Given provider-specific support, the value may be overridden on a per-backend basis.
Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits). These options will only be effective if health check paths are defined.
Given provider-specific support, the value may be overridden on a per-backend basis.
Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits).
If no units are provided, the value is parsed assuming seconds. If no units are provided, the value is parsed assuming seconds.
**Note:** the interval must be greater than the timeout. If configuration doesn't reflect this, the interval will be set to timeout + 1 second.
## Life Cycle ## Life Cycle

View file

@ -71,7 +71,7 @@ Beginning with version 1.4, Traefik respects readiness check results if the Trae
!!! note !!! note
Due to the way readiness check results are currently exposed by the Marathon API, ready tasks may be taken into rotation with a small delay. Due to the way readiness check results are currently exposed by the Marathon API, ready tasks may be taken into rotation with a small delay.
It is on the order of one readiness check timeout interval (as configured on the application specifiation) and guarantees that non-ready tasks do not receive traffic prematurely. It is on the order of one readiness check timeout interval (as configured on the application specification) and guarantees that non-ready tasks do not receive traffic prematurely.
If readiness checks are not possible, a current mitigation strategy is to enable [retries](/configuration/commons#retry-configuration) and make sure that a sufficient number of healthy application tasks exist so that one retry will likely hit one of those. If readiness checks are not possible, a current mitigation strategy is to enable [retries](/configuration/commons#retry-configuration) and make sure that a sufficient number of healthy application tasks exist so that one retry will likely hit one of those.
Apart from its probabilistic nature, the workaround comes at the price of increased latency. Apart from its probabilistic nature, the workaround comes at the price of increased latency.

View file

@ -42,11 +42,12 @@ type Options struct {
Port int Port int
Transport http.RoundTripper Transport http.RoundTripper
Interval time.Duration Interval time.Duration
Timeout time.Duration
LB BalancerHandler LB BalancerHandler
} }
func (opt Options) String() string { func (opt Options) String() string {
return fmt.Sprintf("[Hostname: %s Headers: %v Path: %s Port: %d Interval: %s]", opt.Hostname, opt.Headers, opt.Path, opt.Port, opt.Interval) return fmt.Sprintf("[Hostname: %s Headers: %v Path: %s Port: %d Interval: %s Timeout: %s]", opt.Hostname, opt.Headers, opt.Path, opt.Port, opt.Interval, opt.Timeout)
} }
// BackendConfig HealthCheck configuration for a backend // BackendConfig HealthCheck configuration for a backend
@ -180,9 +181,8 @@ func newHealthCheck(metrics metricsRegistry) *HealthCheck {
// NewBackendConfig Instantiate a new BackendConfig // NewBackendConfig Instantiate a new BackendConfig
func NewBackendConfig(options Options, backendName string) *BackendConfig { func NewBackendConfig(options Options, backendName string) *BackendConfig {
return &BackendConfig{ return &BackendConfig{
Options: options, Options: options,
name: backendName, name: backendName,
requestTimeout: 5 * time.Second,
} }
} }
@ -197,7 +197,7 @@ func checkHealth(serverURL *url.URL, backend *BackendConfig) error {
req = backend.addHeadersAndHost(req) req = backend.addHeadersAndHost(req)
client := http.Client{ client := http.Client{
Timeout: backend.requestTimeout, Timeout: backend.Options.Timeout,
Transport: backend.Options.Transport, Transport: backend.Options.Transport,
} }

View file

@ -15,7 +15,8 @@ import (
"github.com/vulcand/oxy/roundrobin" "github.com/vulcand/oxy/roundrobin"
) )
const healthCheckInterval = 100 * time.Millisecond const healthCheckInterval = 200 * time.Millisecond
const healthCheckTimeout = 100 * time.Millisecond
type testHandler struct { type testHandler struct {
done func() done func()
@ -105,6 +106,7 @@ func TestSetBackendsConfiguration(t *testing.T) {
backend := NewBackendConfig(Options{ backend := NewBackendConfig(Options{
Path: "/path", Path: "/path",
Interval: healthCheckInterval, Interval: healthCheckInterval,
Timeout: healthCheckTimeout,
LB: lb, LB: lb,
}, "backendName") }, "backendName")

View file

@ -83,6 +83,7 @@ func (s *ConsulCatalogSuite) registerAgentService(name string, address string, p
healthCheck = &api.AgentServiceCheck{ healthCheck = &api.AgentServiceCheck{
HTTP: "http://" + address, HTTP: "http://" + address,
Interval: "10s", Interval: "10s",
Timeout: "3s",
} }
} else { } else {
healthCheck = nil healthCheck = nil

View file

@ -18,6 +18,7 @@ logLevel = "DEBUG"
[backends.backend1.healthcheck] [backends.backend1.healthcheck]
path = "/health" path = "/health"
interval = "1s" interval = "1s"
timeout = "0.9s"
[backends.backend1.servers.server1] [backends.backend1.servers.server1]
url = "http://{{.Server1}}:80" url = "http://{{.Server1}}:80"
weight = 1 weight = 1

View file

@ -18,6 +18,7 @@ logLevel = "DEBUG"
[backends.backend1.healthcheck] [backends.backend1.healthcheck]
path = "/health" path = "/health"
interval = "1s" interval = "1s"
timeout = "0.9s"
[backends.backend1.servers.server1] [backends.backend1.servers.server1]
url = "http://{{.Server1}}:80" url = "http://{{.Server1}}:80"
weight = 1 weight = 1

View file

@ -15,6 +15,7 @@ logLevel = "DEBUG"
path = "/health" path = "/health"
port = 80 port = 80
interval = "1s" interval = "1s"
timeout = "0.9s"
[backends.backend1.servers.server1] [backends.backend1.servers.server1]
url = "http://{{.Server1}}:81" url = "http://{{.Server1}}:81"
weight = 1 weight = 1

View file

@ -14,6 +14,7 @@ logLevel = "DEBUG"
[backends.backend1.healthcheck] [backends.backend1.healthcheck]
path = "/health" path = "/health"
interval = "1s" interval = "1s"
timeout = "0.9s"
[backends.backend1.servers.server1] [backends.backend1.servers.server1]
url = "http://{{.Server1}}:80" url = "http://{{.Server1}}:80"
weight = 1 weight = 1

View file

@ -410,6 +410,7 @@ func TestProviderBuildConfiguration(t *testing.T) {
label.TraefikBackendHealthCheckScheme + "=http", label.TraefikBackendHealthCheckScheme + "=http",
label.TraefikBackendHealthCheckPort + "=880", label.TraefikBackendHealthCheckPort + "=880",
label.TraefikBackendHealthCheckInterval + "=6", label.TraefikBackendHealthCheckInterval + "=6",
label.TraefikBackendHealthCheckTimeout + "=3",
label.TraefikBackendHealthCheckHostname + "=foo.com", label.TraefikBackendHealthCheckHostname + "=foo.com",
label.TraefikBackendHealthCheckHeaders + "=Foo:bar || Bar:foo", label.TraefikBackendHealthCheckHeaders + "=Foo:bar || Bar:foo",
label.TraefikBackendLoadBalancerMethod + "=drr", label.TraefikBackendLoadBalancerMethod + "=drr",
@ -691,6 +692,7 @@ func TestProviderBuildConfiguration(t *testing.T) {
Path: "/health", Path: "/health",
Port: 880, Port: 880,
Interval: "6", Interval: "6",
Timeout: "3",
Hostname: "foo.com", Hostname: "foo.com",
Headers: map[string]string{ Headers: map[string]string{
"Foo": "bar", "Foo": "bar",

View file

@ -437,6 +437,7 @@ func TestDockerBuildConfiguration(t *testing.T) {
label.TraefikBackendHealthCheckPath: "/health", label.TraefikBackendHealthCheckPath: "/health",
label.TraefikBackendHealthCheckPort: "880", label.TraefikBackendHealthCheckPort: "880",
label.TraefikBackendHealthCheckInterval: "6", label.TraefikBackendHealthCheckInterval: "6",
label.TraefikBackendHealthCheckTimeout: "3",
label.TraefikBackendHealthCheckHostname: "foo.com", label.TraefikBackendHealthCheckHostname: "foo.com",
label.TraefikBackendHealthCheckHeaders: "Foo:bar || Bar:foo", label.TraefikBackendHealthCheckHeaders: "Foo:bar || Bar:foo",
label.TraefikBackendLoadBalancerMethod: "drr", label.TraefikBackendLoadBalancerMethod: "drr",
@ -683,6 +684,7 @@ func TestDockerBuildConfiguration(t *testing.T) {
Path: "/health", Path: "/health",
Port: 880, Port: 880,
Interval: "6", Interval: "6",
Timeout: "3",
Hostname: "foo.com", Hostname: "foo.com",
Headers: map[string]string{ Headers: map[string]string{
"Foo": "bar", "Foo": "bar",

View file

@ -385,6 +385,7 @@ func TestSwarmBuildConfiguration(t *testing.T) {
label.TraefikBackendHealthCheckPath: "/health", label.TraefikBackendHealthCheckPath: "/health",
label.TraefikBackendHealthCheckPort: "880", label.TraefikBackendHealthCheckPort: "880",
label.TraefikBackendHealthCheckInterval: "6", label.TraefikBackendHealthCheckInterval: "6",
label.TraefikBackendHealthCheckTimeout: "3",
label.TraefikBackendHealthCheckHostname: "foo.com", label.TraefikBackendHealthCheckHostname: "foo.com",
label.TraefikBackendHealthCheckHeaders: "Foo:bar || Bar:foo", label.TraefikBackendHealthCheckHeaders: "Foo:bar || Bar:foo",
label.TraefikBackendLoadBalancerMethod: "drr", label.TraefikBackendLoadBalancerMethod: "drr",
@ -600,6 +601,7 @@ func TestSwarmBuildConfiguration(t *testing.T) {
Path: "/health", Path: "/health",
Port: 880, Port: 880,
Interval: "6", Interval: "6",
Timeout: "3",
Hostname: "foo.com", Hostname: "foo.com",
Headers: map[string]string{ Headers: map[string]string{
"Foo": "bar", "Foo": "bar",

View file

@ -68,7 +68,8 @@ func TestBuildConfiguration(t *testing.T) {
ID("1"), ID("1"),
dockerLabels(map[string]*string{ dockerLabels(map[string]*string{
label.TraefikBackendHealthCheckPath: aws.String("/health"), label.TraefikBackendHealthCheckPath: aws.String("/health"),
label.TraefikBackendHealthCheckInterval: aws.String("1s"), label.TraefikBackendHealthCheckInterval: aws.String("6s"),
label.TraefikBackendHealthCheckTimeout: aws.String("3s"),
}), }),
iMachine( iMachine(
mState(ec2.InstanceStateNameRunning), mState(ec2.InstanceStateNameRunning),
@ -84,7 +85,8 @@ func TestBuildConfiguration(t *testing.T) {
"backend-instance": { "backend-instance": {
HealthCheck: &types.HealthCheck{ HealthCheck: &types.HealthCheck{
Path: "/health", Path: "/health",
Interval: "1s", Interval: "6s",
Timeout: "3s",
}, },
Servers: map[string]types.Server{ Servers: map[string]types.Server{
"server-instance-1": { "server-instance-1": {
@ -343,6 +345,7 @@ func TestBuildConfiguration(t *testing.T) {
label.TraefikBackendHealthCheckPath: aws.String("/health"), label.TraefikBackendHealthCheckPath: aws.String("/health"),
label.TraefikBackendHealthCheckPort: aws.String("880"), label.TraefikBackendHealthCheckPort: aws.String("880"),
label.TraefikBackendHealthCheckInterval: aws.String("6"), label.TraefikBackendHealthCheckInterval: aws.String("6"),
label.TraefikBackendHealthCheckTimeout: aws.String("3"),
label.TraefikBackendHealthCheckHostname: aws.String("foo.com"), label.TraefikBackendHealthCheckHostname: aws.String("foo.com"),
label.TraefikBackendHealthCheckHeaders: aws.String("Foo:bar || Bar:foo"), label.TraefikBackendHealthCheckHeaders: aws.String("Foo:bar || Bar:foo"),
label.TraefikBackendLoadBalancerMethod: aws.String("drr"), label.TraefikBackendLoadBalancerMethod: aws.String("drr"),
@ -470,6 +473,7 @@ func TestBuildConfiguration(t *testing.T) {
Path: "/health", Path: "/health",
Port: 880, Port: 880,
Interval: "6", Interval: "6",
Timeout: "3",
Hostname: "foo.com", Hostname: "foo.com",
Headers: map[string]string{ Headers: map[string]string{
"Foo": "bar", "Foo": "bar",
@ -633,6 +637,7 @@ func TestBuildConfiguration(t *testing.T) {
label.TraefikBackendHealthCheckPath: aws.String("/health"), label.TraefikBackendHealthCheckPath: aws.String("/health"),
label.TraefikBackendHealthCheckPort: aws.String("880"), label.TraefikBackendHealthCheckPort: aws.String("880"),
label.TraefikBackendHealthCheckInterval: aws.String("6"), label.TraefikBackendHealthCheckInterval: aws.String("6"),
label.TraefikBackendHealthCheckTimeout: aws.String("3"),
label.TraefikBackendHealthCheckHostname: aws.String("foo.com"), label.TraefikBackendHealthCheckHostname: aws.String("foo.com"),
label.TraefikBackendHealthCheckHeaders: aws.String("Foo:bar || Bar:foo"), label.TraefikBackendHealthCheckHeaders: aws.String("Foo:bar || Bar:foo"),
label.TraefikBackendLoadBalancerMethod: aws.String("drr"), label.TraefikBackendLoadBalancerMethod: aws.String("drr"),
@ -719,6 +724,7 @@ func TestBuildConfiguration(t *testing.T) {
label.TraefikBackendHealthCheckPath: aws.String("/health"), label.TraefikBackendHealthCheckPath: aws.String("/health"),
label.TraefikBackendHealthCheckPort: aws.String("880"), label.TraefikBackendHealthCheckPort: aws.String("880"),
label.TraefikBackendHealthCheckInterval: aws.String("6"), label.TraefikBackendHealthCheckInterval: aws.String("6"),
label.TraefikBackendHealthCheckTimeout: aws.String("3"),
label.TraefikBackendHealthCheckHostname: aws.String("bar.com"), label.TraefikBackendHealthCheckHostname: aws.String("bar.com"),
label.TraefikBackendHealthCheckHeaders: aws.String("Foo:bar || Bar:foo"), label.TraefikBackendHealthCheckHeaders: aws.String("Foo:bar || Bar:foo"),
label.TraefikBackendLoadBalancerMethod: aws.String("drr"), label.TraefikBackendLoadBalancerMethod: aws.String("drr"),
@ -822,6 +828,7 @@ func TestBuildConfiguration(t *testing.T) {
Path: "/health", Path: "/health",
Port: 880, Port: 880,
Interval: "6", Interval: "6",
Timeout: "3",
Hostname: "foo.com", Hostname: "foo.com",
Headers: map[string]string{ Headers: map[string]string{
"Foo": "bar", "Foo": "bar",

View file

@ -7,6 +7,7 @@ const (
pathBackendHealthCheckPath = "/healthcheck/path" pathBackendHealthCheckPath = "/healthcheck/path"
pathBackendHealthCheckPort = "/healthcheck/port" pathBackendHealthCheckPort = "/healthcheck/port"
pathBackendHealthCheckInterval = "/healthcheck/interval" pathBackendHealthCheckInterval = "/healthcheck/interval"
pathBackendHealthCheckTimeout = "/healthcheck/timeout"
pathBackendHealthCheckHostname = "/healthcheck/hostname" pathBackendHealthCheckHostname = "/healthcheck/hostname"
pathBackendHealthCheckHeaders = "/healthcheck/headers/" pathBackendHealthCheckHeaders = "/healthcheck/headers/"
pathBackendLoadBalancerMethod = "/loadbalancer/method" pathBackendLoadBalancerMethod = "/loadbalancer/method"

View file

@ -271,6 +271,7 @@ func (p *Provider) getHealthCheck(rootPath string) *types.HealthCheck {
scheme := p.get("", rootPath, pathBackendHealthCheckScheme) scheme := p.get("", rootPath, pathBackendHealthCheckScheme)
port := p.getInt(label.DefaultBackendHealthCheckPort, rootPath, pathBackendHealthCheckPort) port := p.getInt(label.DefaultBackendHealthCheckPort, rootPath, pathBackendHealthCheckPort)
interval := p.get("30s", rootPath, pathBackendHealthCheckInterval) interval := p.get("30s", rootPath, pathBackendHealthCheckInterval)
timeout := p.get("5s", rootPath, pathBackendHealthCheckTimeout)
hostname := p.get("", rootPath, pathBackendHealthCheckHostname) hostname := p.get("", rootPath, pathBackendHealthCheckHostname)
headers := p.getMap(rootPath, pathBackendHealthCheckHeaders) headers := p.getMap(rootPath, pathBackendHealthCheckHeaders)
@ -279,6 +280,7 @@ func (p *Provider) getHealthCheck(rootPath string) *types.HealthCheck {
Path: path, Path: path,
Port: port, Port: port,
Interval: interval, Interval: interval,
Timeout: timeout,
Hostname: hostname, Hostname: hostname,
Headers: headers, Headers: headers,
} }

View file

@ -260,6 +260,7 @@ func TestProviderBuildConfiguration(t *testing.T) {
withPair(pathBackendHealthCheckPath, "/health"), withPair(pathBackendHealthCheckPath, "/health"),
withPair(pathBackendHealthCheckPort, "80"), withPair(pathBackendHealthCheckPort, "80"),
withPair(pathBackendHealthCheckInterval, "30s"), withPair(pathBackendHealthCheckInterval, "30s"),
withPair(pathBackendHealthCheckTimeout, "5s"),
withPair(pathBackendHealthCheckHostname, "foo.com"), withPair(pathBackendHealthCheckHostname, "foo.com"),
withPair(pathBackendHealthCheckHeaders+"Foo", "bar"), withPair(pathBackendHealthCheckHeaders+"Foo", "bar"),
withPair(pathBackendHealthCheckHeaders+"Bar", "foo"), withPair(pathBackendHealthCheckHeaders+"Bar", "foo"),
@ -387,6 +388,7 @@ func TestProviderBuildConfiguration(t *testing.T) {
Path: "/health", Path: "/health",
Port: 80, Port: 80,
Interval: "30s", Interval: "30s",
Timeout: "5s",
Hostname: "foo.com", Hostname: "foo.com",
Headers: map[string]string{ Headers: map[string]string{
"Foo": "bar", "Foo": "bar",
@ -1986,9 +1988,12 @@ func TestProviderGetHealthCheck(t *testing.T) {
backend("foo", backend("foo",
withPair(pathBackendHealthCheckPath, "/health"), withPair(pathBackendHealthCheckPath, "/health"),
withPair(pathBackendHealthCheckPort, "80"), withPair(pathBackendHealthCheckPort, "80"),
withPair(pathBackendHealthCheckInterval, "10s"))), withPair(pathBackendHealthCheckInterval, "10s"),
withPair(pathBackendHealthCheckTimeout, "3s"))),
expected: &types.HealthCheck{ expected: &types.HealthCheck{
Interval: "10s", Interval: "10s",
Timeout: "3s",
Path: "/health", Path: "/health",
Port: 80, Port: 80,
}, },
@ -2001,6 +2006,7 @@ func TestProviderGetHealthCheck(t *testing.T) {
withPair(pathBackendHealthCheckPath, "/health"))), withPair(pathBackendHealthCheckPath, "/health"))),
expected: &types.HealthCheck{ expected: &types.HealthCheck{
Interval: "30s", Interval: "30s",
Timeout: "5s",
Path: "/health", Path: "/health",
Port: 0, Port: 0,
}, },
@ -2011,7 +2017,8 @@ func TestProviderGetHealthCheck(t *testing.T) {
kvPairs: filler("traefik", kvPairs: filler("traefik",
backend("foo", backend("foo",
withPair(pathBackendHealthCheckPort, "80"), withPair(pathBackendHealthCheckPort, "80"),
withPair(pathBackendHealthCheckInterval, "30s"))), withPair(pathBackendHealthCheckInterval, "30s"),
withPair(pathBackendHealthCheckTimeout, "5s"))),
expected: nil, expected: nil,
}, },
} }

View file

@ -19,6 +19,7 @@ const (
SuffixBackendHealthCheckPath = "backend.healthcheck.path" SuffixBackendHealthCheckPath = "backend.healthcheck.path"
SuffixBackendHealthCheckPort = "backend.healthcheck.port" SuffixBackendHealthCheckPort = "backend.healthcheck.port"
SuffixBackendHealthCheckInterval = "backend.healthcheck.interval" SuffixBackendHealthCheckInterval = "backend.healthcheck.interval"
SuffixBackendHealthCheckTimeout = "backend.healthcheck.timeout"
SuffixBackendHealthCheckHostname = "backend.healthcheck.hostname" SuffixBackendHealthCheckHostname = "backend.healthcheck.hostname"
SuffixBackendHealthCheckHeaders = "backend.healthcheck.headers" SuffixBackendHealthCheckHeaders = "backend.healthcheck.headers"
SuffixBackendLoadBalancer = "backend.loadbalancer" SuffixBackendLoadBalancer = "backend.loadbalancer"
@ -120,6 +121,7 @@ const (
TraefikBackendHealthCheckPath = Prefix + SuffixBackendHealthCheckPath TraefikBackendHealthCheckPath = Prefix + SuffixBackendHealthCheckPath
TraefikBackendHealthCheckPort = Prefix + SuffixBackendHealthCheckPort TraefikBackendHealthCheckPort = Prefix + SuffixBackendHealthCheckPort
TraefikBackendHealthCheckInterval = Prefix + SuffixBackendHealthCheckInterval TraefikBackendHealthCheckInterval = Prefix + SuffixBackendHealthCheckInterval
TraefikBackendHealthCheckTimeout = Prefix + SuffixBackendHealthCheckTimeout
TraefikBackendHealthCheckHostname = Prefix + SuffixBackendHealthCheckHostname TraefikBackendHealthCheckHostname = Prefix + SuffixBackendHealthCheckHostname
TraefikBackendHealthCheckHeaders = Prefix + SuffixBackendHealthCheckHeaders TraefikBackendHealthCheckHeaders = Prefix + SuffixBackendHealthCheckHeaders
TraefikBackendLoadBalancer = Prefix + SuffixBackendLoadBalancer TraefikBackendLoadBalancer = Prefix + SuffixBackendLoadBalancer

View file

@ -342,6 +342,7 @@ func GetHealthCheck(labels map[string]string) *types.HealthCheck {
scheme := GetStringValue(labels, TraefikBackendHealthCheckScheme, "") scheme := GetStringValue(labels, TraefikBackendHealthCheckScheme, "")
port := GetIntValue(labels, TraefikBackendHealthCheckPort, DefaultBackendHealthCheckPort) port := GetIntValue(labels, TraefikBackendHealthCheckPort, DefaultBackendHealthCheckPort)
interval := GetStringValue(labels, TraefikBackendHealthCheckInterval, "") interval := GetStringValue(labels, TraefikBackendHealthCheckInterval, "")
timeout := GetStringValue(labels, TraefikBackendHealthCheckTimeout, "")
hostname := GetStringValue(labels, TraefikBackendHealthCheckHostname, "") hostname := GetStringValue(labels, TraefikBackendHealthCheckHostname, "")
headers := GetMapValue(labels, TraefikBackendHealthCheckHeaders) headers := GetMapValue(labels, TraefikBackendHealthCheckHeaders)
@ -350,6 +351,7 @@ func GetHealthCheck(labels map[string]string) *types.HealthCheck {
Path: path, Path: path,
Port: port, Port: port,
Interval: interval, Interval: interval,
Timeout: timeout,
Hostname: hostname, Hostname: hostname,
Headers: headers, Headers: headers,
} }

View file

@ -379,6 +379,7 @@ func TestGetHealthCheck(t *testing.T) {
labels: map[string]string{ labels: map[string]string{
TraefikBackendHealthCheckPort: "80", TraefikBackendHealthCheckPort: "80",
TraefikBackendHealthCheckInterval: "6", TraefikBackendHealthCheckInterval: "6",
TraefikBackendHealthCheckTimeout: "3",
}, },
expected: nil, expected: nil,
}, },
@ -388,6 +389,7 @@ func TestGetHealthCheck(t *testing.T) {
TraefikBackendHealthCheckPath: "/health", TraefikBackendHealthCheckPath: "/health",
TraefikBackendHealthCheckPort: "80", TraefikBackendHealthCheckPort: "80",
TraefikBackendHealthCheckInterval: "6", TraefikBackendHealthCheckInterval: "6",
TraefikBackendHealthCheckTimeout: "3",
TraefikBackendHealthCheckHeaders: "Foo:bar || Goo:bir", TraefikBackendHealthCheckHeaders: "Foo:bar || Goo:bir",
TraefikBackendHealthCheckHostname: "traefik", TraefikBackendHealthCheckHostname: "traefik",
TraefikBackendHealthCheckScheme: "http", TraefikBackendHealthCheckScheme: "http",
@ -397,6 +399,7 @@ func TestGetHealthCheck(t *testing.T) {
Path: "/health", Path: "/health",
Port: 80, Port: 80,
Interval: "6", Interval: "6",
Timeout: "3",
Hostname: "traefik", Hostname: "traefik",
Headers: map[string]string{ Headers: map[string]string{
"Foo": "bar", "Foo": "bar",

View file

@ -359,6 +359,7 @@ func TestBuildConfiguration(t *testing.T) {
withLabel(label.TraefikBackendHealthCheckPath, "/health"), withLabel(label.TraefikBackendHealthCheckPath, "/health"),
withLabel(label.TraefikBackendHealthCheckPort, "880"), withLabel(label.TraefikBackendHealthCheckPort, "880"),
withLabel(label.TraefikBackendHealthCheckInterval, "6"), withLabel(label.TraefikBackendHealthCheckInterval, "6"),
withLabel(label.TraefikBackendHealthCheckTimeout, "3"),
withLabel(label.TraefikBackendHealthCheckHostname, "foo.com"), withLabel(label.TraefikBackendHealthCheckHostname, "foo.com"),
withLabel(label.TraefikBackendHealthCheckHeaders, "Foo:bar || Bar:foo"), withLabel(label.TraefikBackendHealthCheckHeaders, "Foo:bar || Bar:foo"),
@ -603,6 +604,7 @@ func TestBuildConfiguration(t *testing.T) {
Path: "/health", Path: "/health",
Port: 880, Port: 880,
Interval: "6", Interval: "6",
Timeout: "3",
Hostname: "foo.com", Hostname: "foo.com",
Headers: map[string]string{ Headers: map[string]string{
"Foo": "bar", "Foo": "bar",
@ -779,6 +781,7 @@ func TestBuildConfigurationSegments(t *testing.T) {
withLabel(label.TraefikBackendHealthCheckPath, "/health"), withLabel(label.TraefikBackendHealthCheckPath, "/health"),
withLabel(label.TraefikBackendHealthCheckPort, "880"), withLabel(label.TraefikBackendHealthCheckPort, "880"),
withLabel(label.TraefikBackendHealthCheckInterval, "6"), withLabel(label.TraefikBackendHealthCheckInterval, "6"),
withLabel(label.TraefikBackendHealthCheckTimeout, "3"),
withLabel(label.TraefikBackendLoadBalancerMethod, "drr"), withLabel(label.TraefikBackendLoadBalancerMethod, "drr"),
withLabel(label.TraefikBackendLoadBalancerStickiness, "true"), withLabel(label.TraefikBackendLoadBalancerStickiness, "true"),
withLabel(label.TraefikBackendLoadBalancerStickinessCookieName, "chocolate"), withLabel(label.TraefikBackendLoadBalancerStickinessCookieName, "chocolate"),
@ -1017,6 +1020,7 @@ func TestBuildConfigurationSegments(t *testing.T) {
Path: "/health", Path: "/health",
Port: 880, Port: 880,
Interval: "6", Interval: "6",
Timeout: "3",
}, },
Buffering: &types.Buffering{ Buffering: &types.Buffering{
MaxResponseBodyBytes: 10485760, MaxResponseBodyBytes: 10485760,

View file

@ -316,6 +316,7 @@ func TestBuildConfiguration(t *testing.T) {
withLabel(label.TraefikBackendHealthCheckPath, "/health"), withLabel(label.TraefikBackendHealthCheckPath, "/health"),
withLabel(label.TraefikBackendHealthCheckPort, "880"), withLabel(label.TraefikBackendHealthCheckPort, "880"),
withLabel(label.TraefikBackendHealthCheckInterval, "6"), withLabel(label.TraefikBackendHealthCheckInterval, "6"),
withLabel(label.TraefikBackendHealthCheckTimeout, "3"),
withLabel(label.TraefikBackendHealthCheckHostname, "foo.com"), withLabel(label.TraefikBackendHealthCheckHostname, "foo.com"),
withLabel(label.TraefikBackendHealthCheckHeaders, "Foo:bar || Bar:foo"), withLabel(label.TraefikBackendHealthCheckHeaders, "Foo:bar || Bar:foo"),
@ -563,6 +564,7 @@ func TestBuildConfiguration(t *testing.T) {
Path: "/health", Path: "/health",
Port: 880, Port: 880,
Interval: "6", Interval: "6",
Timeout: "3",
Hostname: "foo.com", Hostname: "foo.com",
Headers: map[string]string{ Headers: map[string]string{
"Foo": "bar", "Foo": "bar",
@ -696,6 +698,7 @@ func TestBuildConfigurationSegments(t *testing.T) {
withLabel(label.TraefikBackendHealthCheckPath, "/health"), withLabel(label.TraefikBackendHealthCheckPath, "/health"),
withLabel(label.TraefikBackendHealthCheckPort, "880"), withLabel(label.TraefikBackendHealthCheckPort, "880"),
withLabel(label.TraefikBackendHealthCheckInterval, "6"), withLabel(label.TraefikBackendHealthCheckInterval, "6"),
withLabel(label.TraefikBackendHealthCheckTimeout, "3"),
withLabel(label.TraefikBackendHealthCheckHostname, "foo.com"), withLabel(label.TraefikBackendHealthCheckHostname, "foo.com"),
withLabel(label.TraefikBackendHealthCheckHeaders, "Foo:bar || Bar:foo"), withLabel(label.TraefikBackendHealthCheckHeaders, "Foo:bar || Bar:foo"),
withLabel(label.TraefikBackendLoadBalancerMethod, "drr"), withLabel(label.TraefikBackendLoadBalancerMethod, "drr"),
@ -940,6 +943,7 @@ func TestBuildConfigurationSegments(t *testing.T) {
Path: "/health", Path: "/health",
Port: 880, Port: 880,
Interval: "6", Interval: "6",
Timeout: "3",
Hostname: "foo.com", Hostname: "foo.com",
Headers: map[string]string{ Headers: map[string]string{
"Bar": "foo", "Bar": "foo",

View file

@ -45,6 +45,7 @@ func TestProviderBuildConfiguration(t *testing.T) {
label.TraefikBackendHealthCheckPath: "/health", label.TraefikBackendHealthCheckPath: "/health",
label.TraefikBackendHealthCheckPort: "880", label.TraefikBackendHealthCheckPort: "880",
label.TraefikBackendHealthCheckInterval: "6", label.TraefikBackendHealthCheckInterval: "6",
label.TraefikBackendHealthCheckTimeout: "3",
label.TraefikBackendHealthCheckHostname: "foo.com", label.TraefikBackendHealthCheckHostname: "foo.com",
label.TraefikBackendHealthCheckHeaders: "Foo:bar || Bar:foo", label.TraefikBackendHealthCheckHeaders: "Foo:bar || Bar:foo",
label.TraefikBackendLoadBalancerMethod: "drr", label.TraefikBackendLoadBalancerMethod: "drr",
@ -295,6 +296,7 @@ func TestProviderBuildConfiguration(t *testing.T) {
Path: "/health", Path: "/health",
Port: 880, Port: 880,
Interval: "6", Interval: "6",
Timeout: "3",
Hostname: "foo.com", Hostname: "foo.com",
Headers: map[string]string{ Headers: map[string]string{
"Foo": "bar", "Foo": "bar",

View file

@ -90,7 +90,10 @@ func TestServerLoadConfigHealthCheckOptions(t *testing.T) {
for _, healthCheck := range healthChecks { for _, healthCheck := range healthChecks {
t.Run(fmt.Sprintf("%s/hc=%t", lbMethod, healthCheck != nil), func(t *testing.T) { t.Run(fmt.Sprintf("%s/hc=%t", lbMethod, healthCheck != nil), func(t *testing.T) {
globalConfig := configuration.GlobalConfiguration{ globalConfig := configuration.GlobalConfiguration{
HealthCheck: &configuration.HealthCheckConfig{Interval: parse.Duration(5 * time.Second)}, HealthCheck: &configuration.HealthCheckConfig{
Interval: parse.Duration(5 * time.Second),
Timeout: parse.Duration(3 * time.Second),
},
} }
entryPoints := map[string]EntryPoint{ entryPoints := map[string]EntryPoint{
"http": { "http": {
@ -424,6 +427,7 @@ func TestServerMultipleFrontendRules(t *testing.T) {
func TestServerBuildHealthCheckOptions(t *testing.T) { func TestServerBuildHealthCheckOptions(t *testing.T) {
lb := &testLoadBalancer{} lb := &testLoadBalancer{}
globalInterval := 15 * time.Second globalInterval := 15 * time.Second
globalTimeout := 3 * time.Second
testCases := []struct { testCases := []struct {
desc string desc string
@ -452,6 +456,7 @@ func TestServerBuildHealthCheckOptions(t *testing.T) {
Path: "/path", Path: "/path",
Interval: globalInterval, Interval: globalInterval,
LB: lb, LB: lb,
Timeout: 3 * time.Second,
}, },
}, },
{ {
@ -464,6 +469,7 @@ func TestServerBuildHealthCheckOptions(t *testing.T) {
Path: "/path", Path: "/path",
Interval: globalInterval, Interval: globalInterval,
LB: lb, LB: lb,
Timeout: 3 * time.Second,
}, },
}, },
{ {
@ -476,6 +482,49 @@ func TestServerBuildHealthCheckOptions(t *testing.T) {
Path: "/path", Path: "/path",
Interval: 5 * time.Minute, Interval: 5 * time.Minute,
LB: lb, LB: lb,
Timeout: 3 * time.Second,
},
},
{
desc: "unparseable timeout",
hc: &types.HealthCheck{
Path: "/path",
Interval: "15s",
Timeout: "unparseable",
},
expectedOpts: &healthcheck.Options{
Path: "/path",
Interval: globalInterval,
Timeout: globalTimeout,
LB: lb,
},
},
{
desc: "sub-zero timeout",
hc: &types.HealthCheck{
Path: "/path",
Interval: "15s",
Timeout: "-42s",
},
expectedOpts: &healthcheck.Options{
Path: "/path",
Interval: globalInterval,
Timeout: globalTimeout,
LB: lb,
},
},
{
desc: "parseable timeout",
hc: &types.HealthCheck{
Path: "/path",
Interval: "15s",
Timeout: "10s",
},
expectedOpts: &healthcheck.Options{
Path: "/path",
Interval: globalInterval,
Timeout: 10 * time.Second,
LB: lb,
}, },
}, },
} }
@ -485,7 +534,10 @@ func TestServerBuildHealthCheckOptions(t *testing.T) {
t.Run(test.desc, func(t *testing.T) { t.Run(test.desc, func(t *testing.T) {
t.Parallel() t.Parallel()
opts := buildHealthCheckOptions(lb, "backend", test.hc, &configuration.HealthCheckConfig{Interval: parse.Duration(globalInterval)}) opts := buildHealthCheckOptions(lb, "backend", test.hc, &configuration.HealthCheckConfig{
Interval: parse.Duration(globalInterval),
Timeout: parse.Duration(globalTimeout),
})
assert.Equal(t, test.expectedOpts, opts, "health check options") assert.Equal(t, test.expectedOpts, opts, "health check options")
}) })
} }

View file

@ -409,11 +409,28 @@ func buildHealthCheckOptions(lb healthcheck.BalancerHandler, backend string, hc
} }
} }
timeout := time.Duration(hcConfig.Timeout)
if hc.Timeout != "" {
timeoutOverride, err := time.ParseDuration(hc.Timeout)
if err != nil {
log.Errorf("Illegal health check timeout for backend '%s': %s", backend, err)
} else if timeoutOverride <= 0 {
log.Errorf("Health check timeout smaller than zero for backend '%s', backend", backend)
} else {
timeout = timeoutOverride
}
}
if timeout >= interval {
log.Warnf("Health check timeout for backend '%s' should be lower than the health check interval. Interval set to timeout + 1 second (%s).", backend)
}
return &healthcheck.Options{ return &healthcheck.Options{
Scheme: hc.Scheme, Scheme: hc.Scheme,
Path: hc.Path, Path: hc.Path,
Port: hc.Port, Port: hc.Port,
Interval: interval, Interval: interval,
Timeout: timeout,
LB: lb, LB: lb,
Hostname: hc.Hostname, Hostname: hc.Hostname,
Headers: hc.Headers, Headers: hc.Headers,

View file

@ -32,6 +32,7 @@
path = "{{ $healthCheck.Path }}" path = "{{ $healthCheck.Path }}"
port = {{ $healthCheck.Port }} port = {{ $healthCheck.Port }}
interval = "{{ $healthCheck.Interval }}" interval = "{{ $healthCheck.Interval }}"
timeout = "{{ $healthCheck.Timeout }}"
hostname = "{{ $healthCheck.Hostname }}" hostname = "{{ $healthCheck.Hostname }}"
{{if $healthCheck.Headers }} {{if $healthCheck.Headers }}
[backends."backend-{{ $backendName }}".healthCheck.headers] [backends."backend-{{ $backendName }}".healthCheck.headers]

View file

@ -33,6 +33,7 @@
path = "{{ $healthCheck.Path }}" path = "{{ $healthCheck.Path }}"
port = {{ $healthCheck.Port }} port = {{ $healthCheck.Port }}
interval = "{{ $healthCheck.Interval }}" interval = "{{ $healthCheck.Interval }}"
timeout = "{{ $healthCheck.Timeout }}"
hostname = "{{ $healthCheck.Hostname }}" hostname = "{{ $healthCheck.Hostname }}"
{{if $healthCheck.Headers }} {{if $healthCheck.Headers }}
[backends."backend-{{ $backendName }}".healthCheck.headers] [backends."backend-{{ $backendName }}".healthCheck.headers]

View file

@ -32,6 +32,7 @@
path = "{{ $healthCheck.Path }}" path = "{{ $healthCheck.Path }}"
port = {{ $healthCheck.Port }} port = {{ $healthCheck.Port }}
interval = "{{ $healthCheck.Interval }}" interval = "{{ $healthCheck.Interval }}"
timeout = "{{ $healthCheck.Timeout }}"
hostname = "{{ $healthCheck.Hostname }}" hostname = "{{ $healthCheck.Hostname }}"
{{if $healthCheck.Headers }} {{if $healthCheck.Headers }}
[backends."backend-{{ $serviceName }}".healthCheck.headers] [backends."backend-{{ $serviceName }}".healthCheck.headers]

View file

@ -32,6 +32,7 @@
path = "{{ $healthCheck.Path }}" path = "{{ $healthCheck.Path }}"
port = {{ $healthCheck.Port }} port = {{ $healthCheck.Port }}
interval = "{{ $healthCheck.Interval }}" interval = "{{ $healthCheck.Interval }}"
timeout = "{{ $healthCheck.Timeout }}"
hostname = "{{ $healthCheck.Hostname }}" hostname = "{{ $healthCheck.Hostname }}"
{{if $healthCheck.Headers }} {{if $healthCheck.Headers }}
[backends."{{ $backendName }}".healthCheck.headers] [backends."{{ $backendName }}".healthCheck.headers]

View file

@ -35,6 +35,7 @@
path = "{{ $healthCheck.Path }}" path = "{{ $healthCheck.Path }}"
port = {{ $healthCheck.Port }} port = {{ $healthCheck.Port }}
interval = "{{ $healthCheck.Interval }}" interval = "{{ $healthCheck.Interval }}"
timeout = "{{ $healthCheck.Timeout }}"
hostname = "{{ $healthCheck.Hostname }}" hostname = "{{ $healthCheck.Hostname }}"
{{if $healthCheck.Headers }} {{if $healthCheck.Headers }}
[backends.{{ $backendName }}.healthCheck.headers] [backends.{{ $backendName }}.healthCheck.headers]

View file

@ -35,6 +35,7 @@
path = "{{ $healthCheck.Path }}" path = "{{ $healthCheck.Path }}"
port = {{ $healthCheck.Port }} port = {{ $healthCheck.Port }}
interval = "{{ $healthCheck.Interval }}" interval = "{{ $healthCheck.Interval }}"
timeout = "{{ $healthCheck.Timeout }}"
hostname = "{{ $healthCheck.Hostname }}" hostname = "{{ $healthCheck.Hostname }}"
{{if $healthCheck.Headers }} {{if $healthCheck.Headers }}
[backends."backend-{{ $backendName }}".healthCheck.headers] [backends."backend-{{ $backendName }}".healthCheck.headers]

View file

@ -34,6 +34,7 @@
path = "{{ $healthCheck.Path }}" path = "{{ $healthCheck.Path }}"
port = {{ $healthCheck.Port }} port = {{ $healthCheck.Port }}
interval = "{{ $healthCheck.Interval }}" interval = "{{ $healthCheck.Interval }}"
timeout = "{{ $healthCheck.Timeout }}"
hostname = "{{ $healthCheck.Hostname }}" hostname = "{{ $healthCheck.Hostname }}"
{{if $healthCheck.Headers }} {{if $healthCheck.Headers }}
[backends."backend-{{ $backendName }}".healthCheck.headers] [backends."backend-{{ $backendName }}".healthCheck.headers]

View file

@ -74,6 +74,7 @@ type HealthCheck struct {
Path string `json:"path,omitempty"` Path string `json:"path,omitempty"`
Port int `json:"port,omitempty"` Port int `json:"port,omitempty"`
Interval string `json:"interval,omitempty"` Interval string `json:"interval,omitempty"`
Timeout string `json:"timeout,omitempty"`
Hostname string `json:"hostname,omitempty"` Hostname string `json:"hostname,omitempty"`
Headers map[string]string `json:"headers,omitempty"` Headers map[string]string `json:"headers,omitempty"`
} }

View file

@ -632,6 +632,12 @@
<span class="tag is-info">{{ p.healthCheck.interval }}</span> <span class="tag is-info">{{ p.healthCheck.interval }}</span>
</div> </div>
</div> </div>
<div class="control" *ngIf="p.healthCheck.timeout">
<div class="tags has-addons">
<span class="tag is-light">Timeout</span>
<span class="tag is-info">{{ p.healthCheck.timeout }}</span>
</div>
</div>
<div class="control" *ngIf="p.healthCheck.port"> <div class="control" *ngIf="p.healthCheck.port">
<div class="tags has-addons"> <div class="tags has-addons">
<span class="tag is-light">Port</span> <span class="tag is-light">Port</span>