Merge pull request #701 from containous/carry-pr-446

Carry PR 446 - Add sticky session support (round two!)
This commit is contained in:
Emile Vauge 2016-09-30 11:25:26 +02:00 committed by GitHub
commit 38b62d4ae3
12 changed files with 116 additions and 48 deletions

View file

@ -222,6 +222,17 @@ For example:
- Another possible value for `extractorfunc` is `client.ip` which will categorize requests based on client source ip. - Another possible value for `extractorfunc` is `client.ip` which will categorize requests based on client source ip.
- Lastly `extractorfunc` can take the value of `request.header.ANY_HEADER` which will categorize requests based on `ANY_HEADER` that you provide. - Lastly `extractorfunc` can take the value of `request.header.ANY_HEADER` which will categorize requests based on `ANY_HEADER` that you provide.
Sticky sessions are supported with both load balancers. When sticky sessions are enabled, a cookie called `_TRAEFIK_BACKEND` is set on the initial
request. On subsequent requests, the client will be directed to the backend stored in the cookie if it is still healthy. If not, a new backend
will be assigned.
For example:
```toml
[backends]
[backends.backend1]
[backends.backend1.loadbalancer]
sticky = true
```
## Servers ## Servers
Servers are simply defined using a `URL`. You can also apply a custom `weight` to each server (this will be used by load-balancing). Servers are simply defined using a `URL`. You can also apply a custom `weight` to each server (this will be used by load-balancing).

View file

@ -711,6 +711,7 @@ Labels can be used on containers to override default behaviour:
- `traefik.backend.maxconn.amount=10`: set a maximum number of connections to the backend. Must be used in conjunction with the below label to take effect. - `traefik.backend.maxconn.amount=10`: set a maximum number of connections to the backend. Must be used in conjunction with the below label to take effect.
- `traefik.backend.maxconn.extractorfunc=client.ip`: set the function to be used against the request to determine what to limit maximum connections to the backend by. Must be used in conjunction with the above label to take effect. - `traefik.backend.maxconn.extractorfunc=client.ip`: set the function to be used against the request to determine what to limit maximum connections to the backend by. Must be used in conjunction with the above label to take effect.
- `traefik.backend.loadbalancer.method=drr`: override the default `wrr` load balancer algorithm - `traefik.backend.loadbalancer.method=drr`: override the default `wrr` load balancer algorithm
- `traefik.backend.loadbalancer.sticky=true`: enable backend sticky sessions
- `traefik.backend.circuitbreaker.expression=NetworkErrorRatio() > 0.5`: create a [circuit breaker](/basics/#backends) to be used against the backend - `traefik.backend.circuitbreaker.expression=NetworkErrorRatio() > 0.5`: create a [circuit breaker](/basics/#backends) to be used against the backend
- `traefik.port=80`: register this port. Useful when the container exposes multiples ports. - `traefik.port=80`: register this port. Useful when the container exposes multiples ports.
- `traefik.protocol=https`: override the default `http` protocol - `traefik.protocol=https`: override the default `http` protocol
@ -810,6 +811,7 @@ Labels can be used on containers to override default behaviour:
- `traefik.backend.maxconn.amount=10`: set a maximum number of connections to the backend. Must be used in conjunction with the below label to take effect. - `traefik.backend.maxconn.amount=10`: set a maximum number of connections to the backend. Must be used in conjunction with the below label to take effect.
- `traefik.backend.maxconn.extractorfunc=client.ip`: set the function to be used against the request to determine what to limit maximum connections to the backend by. Must be used in conjunction with the above label to take effect. - `traefik.backend.maxconn.extractorfunc=client.ip`: set the function to be used against the request to determine what to limit maximum connections to the backend by. Must be used in conjunction with the above label to take effect.
- `traefik.backend.loadbalancer.method=drr`: override the default `wrr` load balancer algorithm - `traefik.backend.loadbalancer.method=drr`: override the default `wrr` load balancer algorithm
- `traefik.backend.loadbalancer.sticky=true`: enable backend sticky sessions
- `traefik.backend.circuitbreaker.expression=NetworkErrorRatio() > 0.5`: create a [circuit breaker](/basics/#backends) to be used against the backend - `traefik.backend.circuitbreaker.expression=NetworkErrorRatio() > 0.5`: create a [circuit breaker](/basics/#backends) to be used against the backend
- `traefik.portIndex=1`: register port by index in the application's ports array. Useful when the application exposes multiple ports. - `traefik.portIndex=1`: register port by index in the application's ports array. Useful when the application exposes multiple ports.
- `traefik.port=80`: register the explicit application port value. Cannot be used alongside `traefik.portIndex`. - `traefik.port=80`: register the explicit application port value. Cannot be used alongside `traefik.portIndex`.

59
glide.lock generated
View file

@ -1,10 +1,10 @@
hash: c0ac205a859d78847e21d3cd63f427ffba985755c6ae84373e4a20364ba39b05 hash: c0ac205a859d78847e21d3cd63f427ffba985755c6ae84373e4a20364ba39b05
updated: 2016-09-28T16:50:04.352639437+01:00 updated: 2016-09-30T10:57:42.336729457+02:00
imports: imports:
- name: github.com/abbot/go-http-auth - name: github.com/abbot/go-http-auth
version: cb4372376e1e00e9f6ab9ec142e029302c9e7140 version: cb4372376e1e00e9f6ab9ec142e029302c9e7140
- name: github.com/boltdb/bolt - name: github.com/boltdb/bolt
version: fff57c100f4dea1905678da7e90d92429dff2904 version: 5cc10bbbc5c141029940133bb33c9e969512a698
- name: github.com/BurntSushi/toml - name: github.com/BurntSushi/toml
version: 99064174e013895bbd9b025c31100bd1d9b590ca version: 99064174e013895bbd9b025c31100bd1d9b590ca
- name: github.com/BurntSushi/ty - name: github.com/BurntSushi/ty
@ -18,7 +18,7 @@ imports:
- name: github.com/codegangsta/cli - name: github.com/codegangsta/cli
version: 1efa31f08b9333f1bd4882d61f9d668a70cd902e version: 1efa31f08b9333f1bd4882d61f9d668a70cd902e
- name: github.com/codegangsta/negroni - name: github.com/codegangsta/negroni
version: 3f7ce7b928e14ff890b067e5bbbc80af73690a9c version: dc6b9d037e8dab60cbfc09c61d6932537829be8b
- name: github.com/containous/flaeg - name: github.com/containous/flaeg
version: a731c034dda967333efce5f8d276aeff11f8ff87 version: a731c034dda967333efce5f8d276aeff11f8ff87
- name: github.com/containous/mux - name: github.com/containous/mux
@ -32,11 +32,11 @@ imports:
- pkg/pathutil - pkg/pathutil
- pkg/types - pkg/types
- name: github.com/davecgh/go-spew - name: github.com/davecgh/go-spew
version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 version: 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d
subpackages: subpackages:
- spew - spew
- name: github.com/docker/distribution - name: github.com/docker/distribution
version: 99cb7c0946d2f5a38015443e515dc916295064d7 version: 87917f30529e6a7fca8eaff2932424915fb11225
subpackages: subpackages:
- context - context
- digest - digest
@ -116,13 +116,13 @@ imports:
- types/time - types/time
- types/versions - types/versions
- name: github.com/docker/go-connections - name: github.com/docker/go-connections
version: 988efe982fdecb46f01d53465878ff1f2ff411ce version: 990a1a1a70b0da4c4cb70e117971a4f0babfbf1a
subpackages: subpackages:
- nat - nat
- sockets - sockets
- tlsconfig - tlsconfig
- name: github.com/docker/go-units - name: github.com/docker/go-units
version: f2145db703495b2e525c59662db69a7344b00bb8 version: f2d77a61e3c169b43402a0a1e84f06daf29b8190
- name: github.com/docker/libcompose - name: github.com/docker/libcompose
version: d1876c1d68527a49c0aac22a0b161acc7296b740 version: d1876c1d68527a49c0aac22a0b161acc7296b740
subpackages: subpackages:
@ -141,7 +141,7 @@ imports:
- version - version
- yaml - yaml
- name: github.com/docker/libkv - name: github.com/docker/libkv
version: 3fce6a0f26e07da3eac45796a8e255547a47a750 version: 35d3e2084c650109e7bcc7282655b1bc8ba924ff
subpackages: subpackages:
- store - store
- store/boltdb - store/boltdb
@ -151,13 +151,13 @@ imports:
- name: github.com/donovanhide/eventsource - name: github.com/donovanhide/eventsource
version: fd1de70867126402be23c306e1ce32828455d85b version: fd1de70867126402be23c306e1ce32828455d85b
- name: github.com/elazarl/go-bindata-assetfs - name: github.com/elazarl/go-bindata-assetfs
version: 9a6736ed45b44bf3835afeebb3034b57ed329f3e version: 57eb5e1fc594ad4b0b1dbea7b286d299e0cb43c2
- name: github.com/gambol99/go-marathon - name: github.com/gambol99/go-marathon
version: a558128c87724cd7430060ef5aedf39f83937f55 version: a558128c87724cd7430060ef5aedf39f83937f55
- name: github.com/go-check/check - name: github.com/go-check/check
version: 11d3bc7aa68e238947792f30573146a3231fc0f1 version: 4f90aeace3a26ad7021961c297b22c42160c7b25
- name: github.com/gogo/protobuf - name: github.com/gogo/protobuf
version: 89f1976ff373a3e549675d2f212c10f98b6c6316 version: e33835a643a970c11ac74f6333f5f6866387a101
subpackages: subpackages:
- proto - proto
- name: github.com/golang/glog - name: github.com/golang/glog
@ -167,17 +167,18 @@ imports:
subpackages: subpackages:
- query - query
- name: github.com/gorilla/context - name: github.com/gorilla/context
version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42 version: aed02d124ae4a0e94fea4541c8effd05bf0c8296
- name: github.com/hashicorp/consul - name: github.com/hashicorp/consul
version: d5b7530ec593f1ec2a8f8a7c145bcadafa88b572 version: fce7d75609a04eeb9d4bf41c8dc592aac18fc97d
subpackages: subpackages:
- api - api
- name: github.com/hashicorp/go-cleanhttp - name: github.com/hashicorp/go-cleanhttp
version: ad28ea4487f05916463e2423a55166280e8254b5 version: 875fb671b3ddc66f8e2f0acc33829c8cb989a38d
- name: github.com/hashicorp/serf - name: github.com/hashicorp/serf
version: b7a120a5fc494f6dd5e858f42fd0fd4022d6320f version: 6c4672d66fc6312ddde18399262943e21175d831
subpackages: subpackages:
- coordinate - coordinate
- serf
- name: github.com/jarcoal/httpmock - name: github.com/jarcoal/httpmock
version: 145b10d659265440f062c31ea15326166bae56ee version: 145b10d659265440f062c31ea15326166bae56ee
- name: github.com/libkermit/compose - name: github.com/libkermit/compose
@ -219,7 +220,7 @@ imports:
- name: github.com/miekg/dns - name: github.com/miekg/dns
version: 5d001d020961ae1c184f9f8152fdc73810481677 version: 5d001d020961ae1c184f9f8152fdc73810481677
- name: github.com/mitchellh/mapstructure - name: github.com/mitchellh/mapstructure
version: ca63d7c062ee3c9f34db231e352b60012b4fd0c1 version: d2dd0262208475919e1a362f675cfc0e7c10e905
- name: github.com/moul/http2curl - name: github.com/moul/http2curl
version: b1479103caacaa39319f75e7f57fc545287fca0d version: b1479103caacaa39319f75e7f57fc545287fca0d
- name: github.com/NYTimes/gziphandler - name: github.com/NYTimes/gziphandler
@ -227,11 +228,11 @@ imports:
- name: github.com/ogier/pflag - name: github.com/ogier/pflag
version: 45c278ab3607870051a2ea9040bb85fcb8557481 version: 45c278ab3607870051a2ea9040bb85fcb8557481
- name: github.com/opencontainers/runc - name: github.com/opencontainers/runc
version: d9fec4c63b089ddfc267194ecb6cda58a13f072c version: 1a81e9ab1f138c091fe5c86d0883f87716088527
subpackages: subpackages:
- libcontainer/user - libcontainer/user
- name: github.com/parnurzeal/gorequest - name: github.com/parnurzeal/gorequest
version: 29ced6f360a5ac3823a3675b4e29fbab336cc186 version: 045012d33ef41ea146c1b675df9296d0dc1a212d
- name: github.com/pmezard/go-difflib - name: github.com/pmezard/go-difflib
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
subpackages: subpackages:
@ -239,22 +240,22 @@ imports:
- name: github.com/ryanuber/go-glob - name: github.com/ryanuber/go-glob
version: 572520ed46dbddaed19ea3d9541bdd0494163693 version: 572520ed46dbddaed19ea3d9541bdd0494163693
- name: github.com/samuel/go-zookeeper - name: github.com/samuel/go-zookeeper
version: 87e1bca4477a3cc767ca71be023ced183d74e538 version: e64db453f3512cade908163702045e0f31137843
subpackages: subpackages:
- zk - zk
- name: github.com/Sirupsen/logrus - name: github.com/Sirupsen/logrus
version: 3ec0642a7fb6488f65b06f9040adc67e3990296a version: a283a10442df8dc09befd873fab202bf8a253d6a
- name: github.com/streamrail/concurrent-map - name: github.com/streamrail/concurrent-map
version: 8bf1e9bacbf65b10c81d0f4314cf2b1ebef728b5 version: 65a174a3a4188c0b7099acbc6cfa0c53628d3287
- name: github.com/stretchr/objx - name: github.com/stretchr/objx
version: cbeaeb16a013161a98496fad62933b1d21786672 version: cbeaeb16a013161a98496fad62933b1d21786672
- name: github.com/stretchr/testify - name: github.com/stretchr/testify
version: 976c720a22c8eb4eb6a0b4348ad85ad12491a506 version: d77da356e56a7428ad25149ca77381849a6a5232
subpackages: subpackages:
- assert - assert
- mock - mock
- name: github.com/thoas/stats - name: github.com/thoas/stats
version: 152b5d051953fdb6e45f14b6826962aadc032324 version: 79b768ff1780f4e5b0ed132e192bfeefe9f85a9c
- name: github.com/tv42/zbase32 - name: github.com/tv42/zbase32
version: 03389da7e0bf9844767f82690f4d68fc097a1306 version: 03389da7e0bf9844767f82690f4d68fc097a1306
- name: github.com/ugorji/go - name: github.com/ugorji/go
@ -262,7 +263,7 @@ imports:
subpackages: subpackages:
- codec - codec
- name: github.com/unrolled/render - name: github.com/unrolled/render
version: 3f4913244021dede105b62caecfb01f0c1eebeda version: 198ad4d8b8a4612176b804ca10555b222a086b40
- name: github.com/vdemeester/docker-events - name: github.com/vdemeester/docker-events
version: be74d4929ec1ad118df54349fda4b0cba60f849b version: be74d4929ec1ad118df54349fda4b0cba60f849b
- name: github.com/vdemeester/shakers - name: github.com/vdemeester/shakers
@ -284,7 +285,7 @@ imports:
- name: github.com/vulcand/route - name: github.com/vulcand/route
version: cb89d787ddbb1c5849a7ac9f79004c1fd12a4a32 version: cb89d787ddbb1c5849a7ac9f79004c1fd12a4a32
- name: github.com/vulcand/vulcand - name: github.com/vulcand/vulcand
version: 643ca8acff8386e3b276f6feb8ba9b5893dbc4a2 version: 28a4e5c0892167589737b95ceecbcef00295be50
subpackages: subpackages:
- conntracker - conntracker
- plugin - plugin
@ -314,11 +315,11 @@ imports:
- name: gopkg.in/fsnotify.v1 - name: gopkg.in/fsnotify.v1
version: a8a77c9133d2d6fd8334f3260d06f60e8d80a5fb version: a8a77c9133d2d6fd8334f3260d06f60e8d80a5fb
- name: gopkg.in/mgo.v2 - name: gopkg.in/mgo.v2
version: 22287bab4379e1fbf6002fb4eb769888f3fb224c version: 29cc868a5ca65f401ff318143f9408d02f4799cc
subpackages: subpackages:
- bson - bson
- name: gopkg.in/square/go-jose.v1 - name: gopkg.in/square/go-jose.v1
version: aa2e30fdd1fe9dd3394119af66451ae790d50e0d version: e3f973b66b91445ec816dd7411ad1b6495a5a2fc
subpackages: subpackages:
- cipher - cipher
- json - json
@ -336,9 +337,9 @@ testImports:
- name: github.com/libkermit/docker-check - name: github.com/libkermit/docker-check
version: cbe0ef03b3d23070eac4d00ba8828f2cc7f7e5a3 version: cbe0ef03b3d23070eac4d00ba8828f2cc7f7e5a3
- name: github.com/spf13/pflag - name: github.com/spf13/pflag
version: 08b1a584251b5b62f458943640fc8ebd4d50aaa5 version: 5644820622454e71517561946e3d94b9f9db6842
- name: github.com/vbatts/tar-split - name: github.com/vbatts/tar-split
version: bd4c5d64c3e9297f410025a3b1bd0c58f659e721 version: 6810cedb21b2c3d0b9bb8f9af12ff2dc7a2f14df
subpackages: subpackages:
- archive/tar - archive/tar
- tar/asm - tar/asm

View file

@ -252,6 +252,7 @@ func (provider *Docker) loadDockerConfig(containersInspected []dockerData) *type
"hasMaxConnLabels": provider.hasMaxConnLabels, "hasMaxConnLabels": provider.hasMaxConnLabels,
"getMaxConnAmount": provider.getMaxConnAmount, "getMaxConnAmount": provider.getMaxConnAmount,
"getMaxConnExtractorFunc": provider.getMaxConnExtractorFunc, "getMaxConnExtractorFunc": provider.getMaxConnExtractorFunc,
"getSticky": provider.getSticky,
"replace": replace, "replace": replace,
} }
@ -261,18 +262,27 @@ func (provider *Docker) loadDockerConfig(containersInspected []dockerData) *type
}, containersInspected).([]dockerData) }, containersInspected).([]dockerData)
frontends := map[string][]dockerData{} frontends := map[string][]dockerData{}
backends := map[string]dockerData{}
servers := map[string][]dockerData{}
for _, container := range filteredContainers { for _, container := range filteredContainers {
frontendName := provider.getFrontendName(container) frontendName := provider.getFrontendName(container)
frontends[frontendName] = append(frontends[frontendName], container) frontends[frontendName] = append(frontends[frontendName], container)
backendName := provider.getBackend(container)
backends[backendName] = container
servers[backendName] = append(servers[backendName], container)
} }
templateObjects := struct { templateObjects := struct {
Containers []dockerData Containers []dockerData
Frontends map[string][]dockerData Frontends map[string][]dockerData
Backends map[string]dockerData
Servers map[string][]dockerData
Domain string Domain string
}{ }{
filteredContainers, filteredContainers,
frontends, frontends,
backends,
servers,
provider.Domain, provider.Domain,
} }
@ -291,7 +301,9 @@ func (provider *Docker) hasCircuitBreakerLabel(container dockerData) bool {
} }
func (provider *Docker) hasLoadBalancerLabel(container dockerData) bool { func (provider *Docker) hasLoadBalancerLabel(container dockerData) bool {
if _, err := getLabel(container, "traefik.backend.loadbalancer.method"); err != nil { _, errMethod := getLabel(container, "traefik.backend.loadbalancer.method")
_, errSticky := getLabel(container, "traefik.backend.loadbalancer.sticky")
if errMethod != nil && errSticky != nil {
return false return false
} }
return true return true
@ -439,6 +451,13 @@ func (provider *Docker) getWeight(container dockerData) string {
return "1" return "1"
} }
func (provider *Docker) getSticky(container dockerData) string {
if _, err := getLabel(container, "traefik.backend.loadbalancer.sticky"); err == nil {
return "true"
}
return "false"
}
func (provider *Docker) getDomain(container dockerData) string { func (provider *Docker) getDomain(container dockerData) string {
if label, err := getLabel(container, "traefik.domain"); err == nil { if label, err := getLabel(container, "traefik.domain"); err == nil {
return label return label

View file

@ -940,7 +940,6 @@ func TestDockerLoadDockerConfig(t *testing.T) {
}, },
}, },
CircuitBreaker: nil, CircuitBreaker: nil,
LoadBalancer: nil,
}, },
}, },
}, },
@ -1027,7 +1026,6 @@ func TestDockerLoadDockerConfig(t *testing.T) {
}, },
}, },
CircuitBreaker: nil, CircuitBreaker: nil,
LoadBalancer: nil,
}, },
}, },
}, },

View file

@ -138,6 +138,7 @@ func (provider *Marathon) loadMarathonConfig() *types.Configuration {
"getMaxConnAmount": provider.getMaxConnAmount, "getMaxConnAmount": provider.getMaxConnAmount,
"getLoadBalancerMethod": provider.getLoadBalancerMethod, "getLoadBalancerMethod": provider.getLoadBalancerMethod,
"getCircuitBreakerExpression": provider.getCircuitBreakerExpression, "getCircuitBreakerExpression": provider.getCircuitBreakerExpression,
"getSticky": provider.getSticky,
} }
applications, err := provider.marathonClient.Applications(nil) applications, err := provider.marathonClient.Applications(nil)
@ -347,6 +348,13 @@ func (provider *Marathon) getProtocol(task marathon.Task, applications []maratho
return "http" return "http"
} }
func (provider *Marathon) getSticky(application marathon.Application) string {
if sticky, err := provider.getLabel(application, "traefik.backend.loadbalancer.sticky"); err == nil {
return sticky
}
return "false"
}
func (provider *Marathon) getPassHostHeader(application marathon.Application) string { func (provider *Marathon) getPassHostHeader(application marathon.Application) string {
if passHostHeader, err := provider.getLabel(application, "traefik.frontend.passHostHeader"); err == nil { if passHostHeader, err := provider.getLabel(application, "traefik.frontend.passHostHeader"); err == nil {
return passHostHeader return passHostHeader
@ -411,7 +419,9 @@ func (provider *Marathon) hasCircuitBreakerLabels(application marathon.Applicati
} }
func (provider *Marathon) hasLoadBalancerLabels(application marathon.Application) bool { func (provider *Marathon) hasLoadBalancerLabels(application marathon.Application) bool {
if _, err := provider.getLabel(application, "traefik.backend.loadbalancer.method"); err != nil { _, errMethod := provider.getLabel(application, "traefik.backend.loadbalancer.method")
_, errSticky := provider.getLabel(application, "traefik.backend.loadbalancer.sticky")
if errMethod != nil && errSticky != nil {
return false return false
} }
return true return true

View file

@ -107,7 +107,6 @@ func TestMarathonLoadConfig(t *testing.T) {
}, },
}, },
CircuitBreaker: nil, CircuitBreaker: nil,
LoadBalancer: nil,
}, },
}, },
}, },

View file

@ -537,16 +537,30 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo
log.Errorf("Skipping frontend %s...", frontendName) log.Errorf("Skipping frontend %s...", frontendName)
continue frontend continue frontend
} }
lbMethod, err := types.NewLoadBalancerMethod(configuration.Backends[frontend.Backend].LoadBalancer) lbMethod, err := types.NewLoadBalancerMethod(configuration.Backends[frontend.Backend].LoadBalancer)
if err != nil { if err != nil {
log.Errorf("Error loading load balancer method '%+v' for frontend %s: %v", configuration.Backends[frontend.Backend].LoadBalancer, frontendName, err) 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) log.Errorf("Skipping frontend %s...", frontendName)
continue frontend continue frontend
} }
stickysession := configuration.Backends[frontend.Backend].LoadBalancer.Sticky
cookiename := "_TRAEFIK_BACKEND"
var sticky *roundrobin.StickySession
if stickysession {
sticky = roundrobin.NewStickySession(cookiename)
}
switch lbMethod { switch lbMethod {
case types.Drr: case types.Drr:
log.Debugf("Creating load-balancer drr") log.Debugf("Creating load-balancer drr")
rebalancer, _ := roundrobin.NewRebalancer(rr, roundrobin.RebalancerLogger(oxyLogger)) rebalancer, _ := roundrobin.NewRebalancer(rr, roundrobin.RebalancerLogger(oxyLogger))
if stickysession {
log.Debugf("Sticky session with cookie %v", cookiename)
rebalancer, _ = roundrobin.NewRebalancer(rr, roundrobin.RebalancerLogger(oxyLogger), roundrobin.RebalancerStickySession(sticky))
}
lb = rebalancer lb = rebalancer
for serverName, server := range configuration.Backends[frontend.Backend].Servers { for serverName, server := range configuration.Backends[frontend.Backend].Servers {
url, err := url.Parse(server.URL) url, err := url.Parse(server.URL)
@ -565,6 +579,10 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo
} }
case types.Wrr: case types.Wrr:
log.Debugf("Creating load-balancer wrr") log.Debugf("Creating load-balancer wrr")
if stickysession {
log.Debugf("Sticky session with cookie %v", cookiename)
rr, _ = roundrobin.New(saveBackend, roundrobin.EnableStickySession(sticky))
}
lb = rr lb = rr
for serverName, server := range configuration.Backends[frontend.Backend].Servers { for serverName, server := range configuration.Backends[frontend.Backend].Servers {
url, err := url.Parse(server.URL) url, err := url.Parse(server.URL)

View file

@ -1,23 +1,29 @@
[backends]{{range .Containers}} {{$backendServers := .Servers}}
{{if hasCircuitBreakerLabel .}} [backends]{{range $backendName, $backend := .Backends}}
[backends.backend-{{getBackend .}}.circuitbreaker] {{if hasCircuitBreakerLabel $backend}}
expression = "{{getCircuitBreakerExpression .}}" [backends.backend-{{$backendName}}.circuitbreaker]
expression = "{{getCircuitBreakerExpression $backend}}"
{{end}} {{end}}
{{if hasLoadBalancerLabel .}} {{if hasLoadBalancerLabel $backend}}
[backends.backend-{{getBackend .}}.loadbalancer] [backends.backend-{{$backendName}}.loadbalancer]
method = "{{getLoadBalancerMethod .}}" method = "{{getLoadBalancerMethod $backend}}"
sticky = {{getSticky $backend}}
{{end}} {{end}}
{{if hasMaxConnLabels .}} {{if hasMaxConnLabels $backend}}
[backends.backend-{{getBackend .}}.maxconn] [backends.backend-{{$backendName}}.maxconn]
amount = {{getMaxConnAmount . }} amount = {{getMaxConnAmount $backend}}
extractorfunc = "{{getMaxConnExtractorFunc . }}" extractorfunc = "{{getMaxConnExtractorFunc $backend}}"
{{end}}
{{$servers := index $backendServers $backendName}}
{{range $serverName, $server := $servers}}
[backends.backend-{{$backendName}}.servers.server-{{$server.Name | replace "/" "" | replace "." "-"}}]
url = "{{getProtocol $server}}://{{getIPAddress $server}}:{{getPort $server}}"
weight = {{getWeight $server}}
{{end}} {{end}}
[backends.backend-{{getBackend .}}.servers.server-{{.Name | replace "/" "" | replace "." "-"}}]
url = "{{getProtocol .}}://{{getIPAddress .}}:{{getPort .}}"
weight = {{getWeight .}}
{{end}} {{end}}
[frontends]{{range $frontend, $containers := .Frontends}} [frontends]{{range $frontend, $containers := .Frontends}}

View file

@ -12,9 +12,11 @@
{{end}} {{end}}
{{$loadBalancer := Get "" . "/loadbalancer/" "method"}} {{$loadBalancer := Get "" . "/loadbalancer/" "method"}}
{{$sticky := Get "false" . "/loadbalancer/" "sticky"}}
{{with $loadBalancer}} {{with $loadBalancer}}
[backends."{{Last $backend}}".loadBalancer] [backends."{{Last $backend}}".loadBalancer]
method = "{{$loadBalancer}}" method = "{{$loadBalancer}}"
sticky = {{$sticky}}
{{end}} {{end}}
{{$maxConnAmt := Get "" . "/maxconn/" "amount"}} {{$maxConnAmt := Get "" . "/maxconn/" "amount"}}

View file

@ -14,6 +14,7 @@
{{ if hasLoadBalancerLabels . }} {{ if hasLoadBalancerLabels . }}
[backends.backend{{getFrontendBackend . }}.loadbalancer] [backends.backend{{getFrontendBackend . }}.loadbalancer]
method = "{{getLoadBalancerMethod . }}" method = "{{getLoadBalancerMethod . }}"
sticky = {{getSticky .}}
{{end}} {{end}}
{{ if hasCircuitBreakerLabels . }} {{ if hasCircuitBreakerLabels . }}
[backends.backend{{getFrontendBackend . }}.circuitbreaker] [backends.backend{{getFrontendBackend . }}.circuitbreaker]

View file

@ -24,6 +24,7 @@ type MaxConn struct {
// LoadBalancer holds load balancing configuration. // LoadBalancer holds load balancing configuration.
type LoadBalancer struct { type LoadBalancer struct {
Method string `json:"method,omitempty"` Method string `json:"method,omitempty"`
Sticky bool `json:"sticky,omitempty"`
} }
// CircuitBreaker holds circuit breaker configuration. // CircuitBreaker holds circuit breaker configuration.