Skip to content

Commit

Permalink
consul: fetch route updates concurrently
Browse files Browse the repository at this point in the history
The code which updates the routing table from consul was using a
single go routine to fetch data from consul. This can be a slow
process if consul has lots of registered services.

This patch adds an option `registry.consul.serviceMonitors`
to increase the concurrency for the route updates.
  • Loading branch information
magiconair committed Nov 15, 2018
1 parent b6621c6 commit 630a67e
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 2 deletions.
1 change: 1 addition & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ type Consul struct {
CheckTLSSkipVerify bool
CheckDeregisterCriticalServiceAfter string
ChecksRequired string
ServiceMonitors int
}

type Tracing struct {
Expand Down
1 change: 1 addition & 0 deletions config/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ var defaultConfig = &Config{
ServiceAddr: ":9998",
ServiceName: "fabio",
ServiceStatus: []string{"passing"},
ServiceMonitors: 1,
CheckInterval: time.Second,
CheckTimeout: 3 * time.Second,
CheckScheme: "http",
Expand Down
5 changes: 5 additions & 0 deletions config/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ func load(cmdline, environ, envprefix []string, props *properties.Properties) (c
f.BoolVar(&cfg.Registry.Consul.CheckTLSSkipVerify, "registry.consul.register.checkTLSSkipVerify", defaultConfig.Registry.Consul.CheckTLSSkipVerify, "service check TLS verification")
f.StringVar(&cfg.Registry.Consul.CheckDeregisterCriticalServiceAfter, "registry.consul.register.checkDeregisterCriticalServiceAfter", defaultConfig.Registry.Consul.CheckDeregisterCriticalServiceAfter, "critical service deregistration timeout")
f.StringVar(&cfg.Registry.Consul.ChecksRequired, "registry.consul.checksRequired", defaultConfig.Registry.Consul.ChecksRequired, "number of checks which must pass: one or all")
f.IntVar(&cfg.Registry.Consul.ServiceMonitors, "registry.consul.serviceMonitors", defaultConfig.Registry.Consul.ServiceMonitors, "concurrency for route updates")
f.IntVar(&cfg.Runtime.GOGC, "runtime.gogc", defaultConfig.Runtime.GOGC, "sets runtime.GOGC")
f.IntVar(&cfg.Runtime.GOMAXPROCS, "runtime.gomaxprocs", defaultConfig.Runtime.GOMAXPROCS, "sets runtime.GOMAXPROCS")
f.StringVar(&cfg.UI.Access, "ui.access", defaultConfig.UI.Access, "access mode, one of [ro, rw]")
Expand Down Expand Up @@ -244,6 +245,10 @@ func load(cmdline, environ, envprefix []string, props *properties.Properties) (c
cfg.Registry.Consul.CheckScheme = "https"
}

if cfg.Registry.Consul.ServiceMonitors <= 0 {
cfg.Registry.Consul.ServiceMonitors = 1
}

if gzipContentTypesValue != "" {
cfg.Proxy.GZIPContentTypes, err = regexp.Compile(gzipContentTypesValue)
if err != nil {
Expand Down
7 changes: 7 additions & 0 deletions config/load_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,13 @@ func TestLoad(t *testing.T) {
return cfg
},
},
{
args: []string{"-registry.consul.serviceMonitors", "5"},
cfg: func(cfg *Config) *Config {
cfg.Registry.Consul.ServiceMonitors = 5
return cfg
},
},
{
args: []string{"-log.access.format", "foobar"},
cfg: func(cfg *Config) *Config {
Expand Down
10 changes: 10 additions & 0 deletions fabio.properties
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,16 @@
# registry.consul.checksRequired = one


# registry.consul.serviceMonitors configures the concurrency for
# route updates. Fabio will make up to the configured number of
# concurrent calls to Consul to fetch status data for route
# updates.
#
# The default is
#
# registry.consul.serviceMonitors = 1


# glob.matching.disabled disables glob matching on route lookups
# If glob matching is enabled there is a performance decrease
# for every route lookup. At a large number of services (> 500) this
Expand Down
20 changes: 18 additions & 2 deletions registry/consul/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,25 @@ func (w *ServiceMonitor) makeConfig(checks []*api.HealthCheck) string {
m[name][id] = true
}

var config []string
n := w.config.ServiceMonitors
if n <= 0 {
n = 1
}

sem := make(chan int, n)
cfgs := make(chan []string, len(m))
for name, passing := range m {
cfg := w.serviceConfig(name, passing)
name, passing := name, passing
go func() {
sem <- 1
cfgs <- w.serviceConfig(name, passing)
<-sem
}()
}

var config []string
for i := 0; i < len(m); i++ {
cfg := <-cfgs
config = append(config, cfg...)
}

Expand Down

0 comments on commit 630a67e

Please sign in to comment.