mirror of
https://github.com/traefik/traefik.git
synced 2025-08-06 22:57:14 +02:00
Fix concurrent access to balancer status map in WRR and P2C strategies
This commit is contained in:
parent
9a46d35169
commit
ba595bfa98
@ -43,6 +43,7 @@ type rnd interface {
|
|||||||
type Balancer struct {
|
type Balancer struct {
|
||||||
wantsHealthCheck bool
|
wantsHealthCheck bool
|
||||||
|
|
||||||
|
// handlersMu is a mutex to protect the handlers slice, the status and the fenced maps.
|
||||||
handlersMu sync.RWMutex
|
handlersMu sync.RWMutex
|
||||||
handlers []*namedHandler
|
handlers []*namedHandler
|
||||||
// status is a record of which child services of the Balancer are healthy, keyed
|
// status is a record of which child services of the Balancer are healthy, keyed
|
||||||
@ -50,11 +51,12 @@ type Balancer struct {
|
|||||||
// created via Add, and it is later removed or added to the map as needed,
|
// created via Add, and it is later removed or added to the map as needed,
|
||||||
// through the SetStatus method.
|
// through the SetStatus method.
|
||||||
status map[string]struct{}
|
status map[string]struct{}
|
||||||
|
// fenced is the list of terminating yet still serving child services.
|
||||||
|
fenced map[string]struct{}
|
||||||
|
|
||||||
// updaters is the list of hooks that are run (to update the Balancer
|
// updaters is the list of hooks that are run (to update the Balancer
|
||||||
// parent(s)), whenever the Balancer status changes.
|
// parent(s)), whenever the Balancer status changes.
|
||||||
updaters []func(bool)
|
updaters []func(bool)
|
||||||
// fenced is the list of terminating yet still serving child services.
|
|
||||||
fenced map[string]struct{}
|
|
||||||
|
|
||||||
sticky *loadbalancer.Sticky
|
sticky *loadbalancer.Sticky
|
||||||
|
|
||||||
@ -181,7 +183,10 @@ func (b *Balancer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("Error while getting sticky handler")
|
log.Error().Err(err).Msg("Error while getting sticky handler")
|
||||||
} else if h != nil {
|
} else if h != nil {
|
||||||
if _, ok := b.status[h.Name]; ok {
|
b.handlersMu.RLock()
|
||||||
|
_, ok := b.status[h.Name]
|
||||||
|
b.handlersMu.RUnlock()
|
||||||
|
if ok {
|
||||||
if rewrite {
|
if rewrite {
|
||||||
if err := b.sticky.WriteStickyCookie(rw, h.Name); err != nil {
|
if err := b.sticky.WriteStickyCookie(rw, h.Name); err != nil {
|
||||||
log.Error().Err(err).Msg("Writing sticky cookie")
|
log.Error().Err(err).Msg("Writing sticky cookie")
|
||||||
|
@ -27,6 +27,7 @@ type namedHandler struct {
|
|||||||
type Balancer struct {
|
type Balancer struct {
|
||||||
wantsHealthCheck bool
|
wantsHealthCheck bool
|
||||||
|
|
||||||
|
// handlersMu is a mutex to protect the handlers slice, the status and the fenced maps.
|
||||||
handlersMu sync.RWMutex
|
handlersMu sync.RWMutex
|
||||||
handlers []*namedHandler
|
handlers []*namedHandler
|
||||||
// status is a record of which child services of the Balancer are healthy, keyed
|
// status is a record of which child services of the Balancer are healthy, keyed
|
||||||
@ -34,11 +35,12 @@ type Balancer struct {
|
|||||||
// created via Add, and it is later removed or added to the map as needed,
|
// created via Add, and it is later removed or added to the map as needed,
|
||||||
// through the SetStatus method.
|
// through the SetStatus method.
|
||||||
status map[string]struct{}
|
status map[string]struct{}
|
||||||
|
// fenced is the list of terminating yet still serving child services.
|
||||||
|
fenced map[string]struct{}
|
||||||
|
|
||||||
// updaters is the list of hooks that are run (to update the Balancer
|
// updaters is the list of hooks that are run (to update the Balancer
|
||||||
// parent(s)), whenever the Balancer status changes.
|
// parent(s)), whenever the Balancer status changes.
|
||||||
updaters []func(bool)
|
updaters []func(bool)
|
||||||
// fenced is the list of terminating yet still serving child services.
|
|
||||||
fenced map[string]struct{}
|
|
||||||
|
|
||||||
sticky *loadbalancer.Sticky
|
sticky *loadbalancer.Sticky
|
||||||
|
|
||||||
@ -180,7 +182,10 @@ func (b *Balancer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("Error while getting sticky handler")
|
log.Error().Err(err).Msg("Error while getting sticky handler")
|
||||||
} else if h != nil {
|
} else if h != nil {
|
||||||
if _, ok := b.status[h.Name]; ok {
|
b.handlersMu.RLock()
|
||||||
|
_, ok := b.status[h.Name]
|
||||||
|
b.handlersMu.RUnlock()
|
||||||
|
if ok {
|
||||||
if rewrite {
|
if rewrite {
|
||||||
if err := b.sticky.WriteStickyCookie(rw, h.Name); err != nil {
|
if err := b.sticky.WriteStickyCookie(rw, h.Name); err != nil {
|
||||||
log.Error().Err(err).Msg("Writing sticky cookie")
|
log.Error().Err(err).Msg("Writing sticky cookie")
|
||||||
|
Loading…
Reference in New Issue
Block a user