diff --git a/provider/marathon.go b/provider/marathon.go index ecf736c78..2dc7c27bc 100644 --- a/provider/marathon.go +++ b/provider/marathon.go @@ -138,6 +138,7 @@ func (provider *Marathon) loadMarathonConfig() *types.Configuration { "getMaxConnAmount": provider.getMaxConnAmount, "getLoadBalancerMethod": provider.getLoadBalancerMethod, "getCircuitBreakerExpression": provider.getCircuitBreakerExpression, + "getSticky": provider.getSticky, } applications, err := provider.marathonClient.Applications(nil) @@ -347,6 +348,13 @@ func (provider *Marathon) getProtocol(task marathon.Task, applications []maratho return "http" } +func (provider *Marathon) getSticky(application marathon.Application) string { + if sticky, err := provider.getLabel(application, "traefik.backend.sticky"); err == nil { + return sticky + } + return "false" +} + func (provider *Marathon) getPassHostHeader(application marathon.Application) string { if passHostHeader, err := provider.getLabel(application, "traefik.frontend.passHostHeader"); err == nil { return passHostHeader diff --git a/provider/marathon_test.go b/provider/marathon_test.go index cb4edea27..4211f1d26 100644 --- a/provider/marathon_test.go +++ b/provider/marathon_test.go @@ -107,7 +107,7 @@ func TestMarathonLoadConfig(t *testing.T) { }, }, CircuitBreaker: nil, - LoadBalancer: nil, + LoadBalancer: &types.LoadBalancer{Sticky: false}, }, }, }, diff --git a/server.go b/server.go index 0d6cf7fb6..ab51614c5 100644 --- a/server.go +++ b/server.go @@ -537,12 +537,16 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo log.Errorf("Skipping frontend %s...", frontendName) continue frontend } + lbMethod, err := types.NewLoadBalancerMethod(configuration.Backends[frontend.Backend].LoadBalancer) if err != nil { log.Errorf("Error loading load balancer method '%+v' for frontend %s: %v", configuration.Backends[frontend.Backend].LoadBalancer, frontendName, err) log.Errorf("Skipping frontend %s...", frontendName) continue frontend } + + stickysession := configuration.Backends[frontend.Backend].LoadBalancer.Sticky + switch lbMethod { case types.Drr: log.Debugf("Creating load-balancer drr") @@ -565,6 +569,12 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo } case types.Wrr: log.Debugf("Creating load-balancer wrr") + if stickysession { + cookiename := "_TRAEFIK_SERVERNAME" + log.Debugf("... setting to sticky session with cookie named %v", cookiename) + sticky := roundrobin.NewStickySession(cookiename) + rr, _ = roundrobin.New(saveBackend, roundrobin.EnableStickySession(sticky)) + } lb = rr for serverName, server := range configuration.Backends[frontend.Backend].Servers { url, err := url.Parse(server.URL) diff --git a/templates/marathon.tmpl b/templates/marathon.tmpl index fbd2bf801..04a6912c2 100644 --- a/templates/marathon.tmpl +++ b/templates/marathon.tmpl @@ -14,6 +14,7 @@ {{ if hasLoadBalancerLabels . }} [backends.backend{{getFrontendBackend . }}.loadbalancer] method = "{{getLoadBalancerMethod . }}" + sticky = {{getSticky .}} {{end}} {{ if hasCircuitBreakerLabels . }} [backends.backend{{getFrontendBackend . }}.circuitbreaker] diff --git a/types/types.go b/types/types.go index 8b4d2a264..d5a0f0ead 100644 --- a/types/types.go +++ b/types/types.go @@ -24,6 +24,7 @@ type MaxConn struct { // LoadBalancer holds load balancing configuration. type LoadBalancer struct { Method string `json:"method,omitempty"` + Sticky bool `json:"sticky,omitempty"` } // CircuitBreaker holds circuit breaker configuration.