From 46e162e6a93679a6563156c56a1e223a20dda79a Mon Sep 17 00:00:00 2001 From: emile Date: Thu, 8 Oct 2015 17:56:45 +0200 Subject: [PATCH] Add backend throttle duration, resolves https://github.com/EmileVauge/traefik/issues/46 --- configuration.go | 31 +++++++++++++++++-------------- docs/index.md | 10 ++++++++++ traefik.go | 29 +++++++++++++++++++++++++++-- traefik.sample.toml | 10 ++++++++++ 4 files changed, 64 insertions(+), 16 deletions(-) diff --git a/configuration.go b/configuration.go index 6a1cb4ace..efdfef429 100644 --- a/configuration.go +++ b/configuration.go @@ -3,23 +3,25 @@ package main import ( "errors" "strings" + "time" ) type GlobalConfiguration struct { - Port string - GraceTimeOut int64 - AccessLogsFile string - TraefikLogsFile string - CertFile, KeyFile string - LogLevel string - Docker *DockerProvider - File *FileProvider - Web *WebProvider - Marathon *MarathonProvider - Consul *ConsulProvider - Etcd *EtcdProvider - Zookeeper *ZookepperProvider - Boltdb *BoltDbProvider + Port string + GraceTimeOut int64 + AccessLogsFile string + TraefikLogsFile string + CertFile, KeyFile string + LogLevel string + BackendsThrottleDuration time.Duration + Docker *DockerProvider + File *FileProvider + Web *WebProvider + Marathon *MarathonProvider + Consul *ConsulProvider + Etcd *EtcdProvider + Zookeeper *ZookepperProvider + Boltdb *BoltDbProvider } func NewGlobalConfiguration() *GlobalConfiguration { @@ -28,6 +30,7 @@ func NewGlobalConfiguration() *GlobalConfiguration { globalConfiguration.Port = ":80" globalConfiguration.GraceTimeOut = 10 globalConfiguration.LogLevel = "ERROR" + globalConfiguration.BackendsThrottleDuration = time.Duration(2 * time.Second) return globalConfiguration } diff --git a/docs/index.md b/docs/index.md index 28f557a69..5644af607 100644 --- a/docs/index.md +++ b/docs/index.md @@ -107,6 +107,16 @@ For example: # # CertFile = "traefik.crt" # KeyFile = "traefik.key" + +# 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. +# +# Optional +# Default: "2s" +# +# BackendsThrottleDuration = "5s" + ``` diff --git a/traefik.go b/traefik.go index 8b63f3dbf..4a3464f30 100644 --- a/traefik.go +++ b/traefik.go @@ -59,6 +59,8 @@ func main() { var configurationRouter *mux.Router var configurationChan = make(chan configMessage, 10) defer close(configurationChan) + var configurationChanValidated = make(chan configMessage, 10) + defer close(configurationChanValidated) var sigs = make(chan os.Signal, 1) defer close(sigs) var stopChan = make(chan bool) @@ -96,10 +98,33 @@ func main() { // listen new configurations from providers go func() { - + lastReceivedConfiguration := time.Unix(0, 0) + lastConfigs := make(map[string]*configMessage) for { configMsg := <-configurationChan log.Infof("Configuration receveived from provider %s: %#v", configMsg.providerName, configMsg.configuration) + lastConfigs[configMsg.providerName] = &configMsg + if time.Now().After(lastReceivedConfiguration.Add(time.Duration(globalConfiguration.BackendsThrottleDuration))) { + log.Infof("Last %s config received more than %s, OK", configMsg.providerName, globalConfiguration.BackendsThrottleDuration) + // last config received more than n s ago + configurationChanValidated <- configMsg + } else { + log.Infof("Last %s config received less than %s, waiting...", configMsg.providerName, globalConfiguration.BackendsThrottleDuration) + go func() { + <-time.After(globalConfiguration.BackendsThrottleDuration) + if time.Now().After(lastReceivedConfiguration.Add(time.Duration(globalConfiguration.BackendsThrottleDuration))) { + log.Infof("Waited for %s config, OK", configMsg.providerName) + configurationChanValidated <- *lastConfigs[configMsg.providerName] + } + }() + } + lastReceivedConfiguration = time.Now() + } + }() + go func() { + for { + configMsg := <-configurationChanValidated + log.Debugf("Configuration %s", spew.Sdump(configMsg.configuration)) if configMsg.configuration == nil { log.Info("Skipping empty configuration") } else if reflect.DeepEqual(currentConfigurations[configMsg.providerName], configMsg.configuration) { @@ -120,7 +145,7 @@ func main() { newsrv := prepareServer(configurationRouter, globalConfiguration, oldServer, loggerMiddleware, metrics) go startServer(newsrv, globalConfiguration) srv = newsrv - time.Sleep(2 * time.Second) + time.Sleep(1 * time.Second) if oldServer != nil { log.Info("Stopping old server") oldServer.Close() diff --git a/traefik.sample.toml b/traefik.sample.toml index 51d452609..9d824343c 100644 --- a/traefik.sample.toml +++ b/traefik.sample.toml @@ -44,6 +44,16 @@ # CertFile = "traefik.crt" # KeyFile = "traefik.key" +# 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. +# +# Optional +# Default: "2s" +# +# BackendsThrottleDuration = "5s" + + ################################################################ # Web configuration backend ################################################################