diff --git a/configuration.go b/configuration.go index e7d45ea64..af0b65300 100644 --- a/configuration.go +++ b/configuration.go @@ -9,6 +9,7 @@ import ( "strings" "time" + "github.com/containous/flaeg" "github.com/containous/traefik/acme" "github.com/containous/traefik/provider" "github.com/containous/traefik/types" @@ -23,7 +24,7 @@ type TraefikConfiguration struct { // GlobalConfiguration holds global configuration (with providers, etc.). // It's populated from the traefik configuration file passed as an argument to the binary. type GlobalConfiguration struct { - GraceTimeOut int64 `short:"g" description:"Duration to give active requests a chance to finish during hot-reload"` + GraceTimeOut flaeg.Duration `short:"g" description:"Duration to give active requests a chance to finish during hot-reload"` Debug bool `short:"d" description:"Enable debug mode"` CheckNewVersion bool `description:"Periodically check if a new version has been released"` AccessLogsFile string `description:"Access logs file"` @@ -34,7 +35,7 @@ type GlobalConfiguration struct { Constraints types.Constraints `description:"Filter services by constraint, matching with service tags"` ACME *acme.ACME `description:"Enable ACME (Let's Encrypt): automatic SSL"` DefaultEntryPoints DefaultEntryPoints `description:"Entrypoints to be used by frontends that do not specify any entrypoint"` - ProvidersThrottleDuration time.Duration `description:"Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time."` + ProvidersThrottleDuration flaeg.Duration `description:"Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time."` MaxIdleConnsPerHost int `description:"If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used"` InsecureSkipVerify bool `description:"Disable SSL certificate verification"` Retry *Retry `description:"Enable retry sending request if network error"` @@ -457,14 +458,14 @@ func NewTraefikDefaultPointersConfiguration() *TraefikConfiguration { func NewTraefikConfiguration() *TraefikConfiguration { return &TraefikConfiguration{ GlobalConfiguration: GlobalConfiguration{ - GraceTimeOut: 10, + GraceTimeOut: flaeg.Duration(10 * time.Second), AccessLogsFile: "", TraefikLogsFile: "", LogLevel: "ERROR", EntryPoints: map[string]*EntryPoint{}, Constraints: types.Constraints{}, DefaultEntryPoints: []string{}, - ProvidersThrottleDuration: time.Duration(2 * time.Second), + ProvidersThrottleDuration: flaeg.Duration(2 * time.Second), MaxIdleConnsPerHost: 200, CheckNewVersion: true, }, diff --git a/docs/toml.md b/docs/toml.md index e49f82e27..20d44acf8 100644 --- a/docs/toml.md +++ b/docs/toml.md @@ -9,13 +9,15 @@ # Global configuration ################################################################ -# Timeout in seconds. -# Duration to give active requests a chance to finish during hot-reloads +# Duration to give active requests a chance to finish during hot-reloads. +# 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. # # Optional -# Default: 10 +# Default: "10s" # -# graceTimeOut = 10 +# graceTimeOut = "10s" # Enable debug mode # @@ -56,11 +58,14 @@ # Backends throttle duration: minimum duration in seconds between 2 events from providers # before applying a new configuration. It avoids unnecessary reloads if multiples events # are sent in a short amount of time. +# 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. # # Optional -# Default: "2" +# Default: "2s" # -# ProvidersThrottleDuration = "5" +# ProvidersThrottleDuration = "2s" # If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used. # If you encounter 'too many open files' errors, you can either change this value, or change `ulimit` value. @@ -932,19 +937,25 @@ domain = "marathon.localhost" # dcosToken = "xxxxxx" # Override DialerTimeout -# Amount of time in seconds to allow the Marathon provider to wait to open a TCP -# connection to a Marathon master +# Amount of time to allow the Marathon provider to wait to open a TCP connection +# to a Marathon master. +# 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. # # Optional -# Default: 60 -# dialerTimeout = 5 +# Default: "60s" +# dialerTimeout = "60s" -# Set the TCP Keep Alive interval (in seconds) for the Marathon HTTP Client +# Set the TCP Keep Alive interval for the Marathon HTTP Client. +# 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. # # Optional -# Default: 10 +# Default: "10s" # -# keepAlive = 10 +# keepAlive = "10s" ``` Labels can be used on containers to override default behaviour: diff --git a/provider/marathon.go b/provider/marathon.go index 2e54248f3..8d45ba5ec 100644 --- a/provider/marathon.go +++ b/provider/marathon.go @@ -13,6 +13,7 @@ import ( "github.com/BurntSushi/ty/fun" "github.com/cenk/backoff" + "github.com/containous/flaeg" "github.com/containous/traefik/job" "github.com/containous/traefik/log" "github.com/containous/traefik/safe" @@ -25,15 +26,15 @@ var _ Provider = (*Marathon)(nil) // Marathon holds configuration of the Marathon provider. type Marathon struct { BaseProvider - Endpoint string `description:"Marathon server endpoint. You can also specify multiple endpoint for Marathon"` - Domain string `description:"Default domain used"` - ExposedByDefault bool `description:"Expose Marathon apps by default"` - GroupsAsSubDomains bool `description:"Convert Marathon groups to subdomains"` - DCOSToken string `description:"DCOSToken for DCOS environment, This will override the Authorization header"` - MarathonLBCompatibility bool `description:"Add compatibility with marathon-lb labels"` - TLS *ClientTLS `description:"Enable Docker TLS support"` - DialerTimeout time.Duration `description:"Set a non-default connection timeout for Marathon"` - KeepAlive time.Duration `description:"Set a non-default TCP Keep Alive time in seconds"` + Endpoint string `description:"Marathon server endpoint. You can also specify multiple endpoint for Marathon"` + Domain string `description:"Default domain used"` + ExposedByDefault bool `description:"Expose Marathon apps by default"` + GroupsAsSubDomains bool `description:"Convert Marathon groups to subdomains"` + DCOSToken string `description:"DCOSToken for DCOS environment, This will override the Authorization header"` + MarathonLBCompatibility bool `description:"Add compatibility with marathon-lb labels"` + TLS *ClientTLS `description:"Enable Docker TLS support"` + DialerTimeout flaeg.Duration `description:"Set a non-default connection timeout for Marathon"` + KeepAlive flaeg.Duration `description:"Set a non-default TCP Keep Alive time in seconds"` Basic *MarathonBasic marathonClient marathon.Marathon } @@ -71,8 +72,8 @@ func (provider *Marathon) Provide(configurationChan chan<- types.ConfigMessage, config.HTTPClient = &http.Client{ Transport: &http.Transport{ DialContext: (&net.Dialer{ - KeepAlive: provider.KeepAlive * time.Second, - Timeout: time.Second * provider.DialerTimeout, + KeepAlive: time.Duration(provider.KeepAlive), + Timeout: time.Duration(provider.DialerTimeout), }).DialContext, TLSClientConfig: TLSConfig, }, diff --git a/server.go b/server.go index 86adb9c86..ed12e88d4 100644 --- a/server.go +++ b/server.go @@ -20,6 +20,8 @@ import ( "syscall" "time" + "sync" + "github.com/codegangsta/negroni" "github.com/containous/mux" "github.com/containous/traefik/cluster" @@ -35,7 +37,6 @@ import ( "github.com/vulcand/oxy/forward" "github.com/vulcand/oxy/roundrobin" "github.com/vulcand/oxy/utils" - "sync" ) var oxyLogger = &OxyLogger{} @@ -120,8 +121,9 @@ func (server *Server) Stop() { wg.Add(1) go func(serverEntryPointName string, serverEntryPoint *serverEntryPoint) { defer wg.Done() - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(server.globalConfiguration.GraceTimeOut)*time.Second) - log.Debugf("Waiting %d seconds before killing connections on entrypoint %s...", server.globalConfiguration.GraceTimeOut, serverEntryPointName) + graceTimeOut := time.Duration(server.globalConfiguration.GraceTimeOut) + ctx, cancel := context.WithTimeout(context.Background(), graceTimeOut) + log.Debugf("Waiting %s seconds before killing connections on entrypoint %s...", graceTimeOut, serverEntryPointName) if err := serverEntryPoint.httpServer.Shutdown(ctx); err != nil { log.Debugf("Wait is over due to: %s", err) serverEntryPoint.httpServer.Close() @@ -136,7 +138,7 @@ func (server *Server) Stop() { // Close destroys the server func (server *Server) Close() { - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(server.globalConfiguration.GraceTimeOut)*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), time.Duration(server.globalConfiguration.GraceTimeOut)) go func(ctx context.Context) { <-ctx.Done() if ctx.Err() == context.Canceled { @@ -231,16 +233,17 @@ func (server *Server) listenProviders(stop chan bool) { } else { lastConfigs.Set(configMsg.ProviderName, &configMsg) lastReceivedConfigurationValue := lastReceivedConfiguration.Get().(time.Time) - if time.Now().After(lastReceivedConfigurationValue.Add(time.Duration(server.globalConfiguration.ProvidersThrottleDuration))) { + providersThrottleDuration := time.Duration(server.globalConfiguration.ProvidersThrottleDuration) + if time.Now().After(lastReceivedConfigurationValue.Add(providersThrottleDuration)) { log.Debugf("Last %s config received more than %s, OK", configMsg.ProviderName, server.globalConfiguration.ProvidersThrottleDuration.String()) // last config received more than n s ago server.configurationValidatedChan <- configMsg } else { log.Debugf("Last %s config received less than %s, waiting...", configMsg.ProviderName, server.globalConfiguration.ProvidersThrottleDuration.String()) safe.Go(func() { - <-time.After(server.globalConfiguration.ProvidersThrottleDuration) + <-time.After(providersThrottleDuration) lastReceivedConfigurationValue := lastReceivedConfiguration.Get().(time.Time) - if time.Now().After(lastReceivedConfigurationValue.Add(time.Duration(server.globalConfiguration.ProvidersThrottleDuration))) { + if time.Now().After(lastReceivedConfigurationValue.Add(time.Duration(providersThrottleDuration))) { log.Debugf("Waited for %s config, OK", configMsg.ProviderName) if lastConfig, ok := lastConfigs.Get(configMsg.ProviderName); ok { server.configurationValidatedChan <- *lastConfig.(*types.ConfigMessage) diff --git a/traefik.sample.toml b/traefik.sample.toml index 6acc66483..8b125a7f6 100644 --- a/traefik.sample.toml +++ b/traefik.sample.toml @@ -2,13 +2,15 @@ # Global configuration ################################################################ -# Timeout in seconds. -# Duration to give active requests a chance to finish during hot-reloads +# Duration to give active requests a chance to finish during hot-reloads. +# Can be provided in a format supported by Go's time.ParseDuration function or +# as raw values (digits). If no units are provided, the value is parsed assuming +# seconds. # # Optional -# Default: 10 +# Default: "10s" # -# graceTimeOut = 10 +# graceTimeOut = "10s" # Enable debug mode # @@ -47,11 +49,14 @@ # Backends throttle duration: minimum duration in seconds between 2 events from providers # before applying a new configuration. It avoids unnecessary reloads if multiples events # are sent in a short amount of time. +# Can be provided in a format supported by Go's time.ParseDuration function or +# as raw values (digits). If no units are provided, the value is parsed assuming +# seconds. # # Optional -# Default: "2" +# Default: "2s" # -# ProvidersThrottleDuration = "5" +# ProvidersThrottleDuration = "5s" # If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used. # If you encounter 'too many open files' errors, you can either change this value, or change `ulimit` value. @@ -557,12 +562,15 @@ # groupsAsSubDomains = true # Override DialerTimeout -# Amount of time in seconds to allow the Marathon provider to wait to open a TCP -# connection to a Marathon master +# Amount of time to allow the Marathon provider to wait to open a TCP connection +# to a Marathon master. +# Can be provided in a format supported by Go's time.ParseDuration function or +# as raw values (digits). If no units are provided, the value is parsed assuming +# seconds. # # Optional -# Default: 60 -# dialerTimeout = 5 +# Default: "60s" +# dialerTimeout = "60s" # Enable Marathon basic authentication # @@ -579,12 +587,15 @@ # dcosToken = "xxxxxx" -# Set the TCP Keep Alive interval (in seconds) for the Marathon HTTP Client +# Set the TCP Keep Alive interval for the Marathon HTTP Client. +# Can be provided in a format supported by Go's time.ParseDuration function or +# as raw values (digits). If no units are provided, the value is parsed assuming +# seconds. # # Optional -# Default: 10 +# Default: "10s" # -# keepAlive = 10 +# keepAlive = "10s" ################################################################ # Mesos configuration backend