From 46e162e6a93679a6563156c56a1e223a20dda79a Mon Sep 17 00:00:00 2001 From: emile Date: Thu, 8 Oct 2015 17:56:45 +0200 Subject: [PATCH 1/3] 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 ################################################################ From 2e5f4598f0b5f8c3b2faafef0a906f4733f43f6f Mon Sep 17 00:00:00 2001 From: emile Date: Thu, 8 Oct 2015 18:39:56 +0200 Subject: [PATCH 2/3] Corrects marathon test --- integration/marathon_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration/marathon_test.go b/integration/marathon_test.go index bcabb9a5c..f8b969fb0 100644 --- a/integration/marathon_test.go +++ b/integration/marathon_test.go @@ -10,7 +10,7 @@ import ( ) func (s *MarathonSuite) TestSimpleConfiguration(c *check.C) { - cmd := exec.Command(traefikBinary, "fixtures/consul/simple.toml") + cmd := exec.Command(traefikBinary, "fixtures/marathon/simple.toml") err := cmd.Start() c.Assert(err, checker.IsNil) @@ -18,7 +18,7 @@ func (s *MarathonSuite) TestSimpleConfiguration(c *check.C) { // TODO validate : run on 80 resp, err := http.Get("http://127.0.0.1/") - // Expected a 404 as we did not comfigure anything + // Expected a 404 as we did not configure anything c.Assert(err, checker.IsNil) c.Assert(resp.StatusCode, checker.Equals, 404) From a0df7ab9212acbc4cb95c235a8518df652ce36f6 Mon Sep 17 00:00:00 2001 From: Vincent Demeester Date: Sat, 17 Oct 2015 14:14:20 +0200 Subject: [PATCH 3/3] Rename BackendsThrottleDuration to ProvidersThrottleDuration Signed-off-by: Vincent Demeester --- configuration.go | 32 ++++++++++++++++---------------- docs/index.md | 2 +- traefik.go | 11 +++++------ traefik.sample.toml | 2 +- 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/configuration.go b/configuration.go index efdfef429..8507ab4c9 100644 --- a/configuration.go +++ b/configuration.go @@ -7,21 +7,21 @@ import ( ) type GlobalConfiguration struct { - 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 + Port string + GraceTimeOut int64 + AccessLogsFile string + TraefikLogsFile string + CertFile, KeyFile string + LogLevel string + ProvidersThrottleDuration time.Duration + Docker *DockerProvider + File *FileProvider + Web *WebProvider + Marathon *MarathonProvider + Consul *ConsulProvider + Etcd *EtcdProvider + Zookeeper *ZookepperProvider + Boltdb *BoltDbProvider } func NewGlobalConfiguration() *GlobalConfiguration { @@ -30,7 +30,7 @@ func NewGlobalConfiguration() *GlobalConfiguration { globalConfiguration.Port = ":80" globalConfiguration.GraceTimeOut = 10 globalConfiguration.LogLevel = "ERROR" - globalConfiguration.BackendsThrottleDuration = time.Duration(2 * time.Second) + globalConfiguration.ProvidersThrottleDuration = time.Duration(2 * time.Second) return globalConfiguration } diff --git a/docs/index.md b/docs/index.md index 5644af607..ffdd05d7b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -115,7 +115,7 @@ For example: # Optional # Default: "2s" # -# BackendsThrottleDuration = "5s" +# ProvidersThrottleDuration = "5s" ``` diff --git a/traefik.go b/traefik.go index 4a3464f30..dd6139353 100644 --- a/traefik.go +++ b/traefik.go @@ -104,15 +104,15 @@ func main() { 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) + if time.Now().After(lastReceivedConfiguration.Add(time.Duration(globalConfiguration.ProvidersThrottleDuration))) { + log.Infof("Last %s config received more than %s, OK", configMsg.providerName, globalConfiguration.ProvidersThrottleDuration) // 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) + log.Infof("Last %s config received less than %s, waiting...", configMsg.providerName, globalConfiguration.ProvidersThrottleDuration) go func() { - <-time.After(globalConfiguration.BackendsThrottleDuration) - if time.Now().After(lastReceivedConfiguration.Add(time.Duration(globalConfiguration.BackendsThrottleDuration))) { + <-time.After(globalConfiguration.ProvidersThrottleDuration) + if time.Now().After(lastReceivedConfiguration.Add(time.Duration(globalConfiguration.ProvidersThrottleDuration))) { log.Infof("Waited for %s config, OK", configMsg.providerName) configurationChanValidated <- *lastConfigs[configMsg.providerName] } @@ -124,7 +124,6 @@ func main() { 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) { diff --git a/traefik.sample.toml b/traefik.sample.toml index 9d824343c..d07b2fbc2 100644 --- a/traefik.sample.toml +++ b/traefik.sample.toml @@ -51,7 +51,7 @@ # Optional # Default: "2s" # -# BackendsThrottleDuration = "5s" +# ProvidersThrottleDuration = "5s" ################################################################