Skip to content

Commit

Permalink
Fix unprotected shared state in load balancer
Browse files Browse the repository at this point in the history
  • Loading branch information
thockin committed Feb 23, 2015
1 parent e88134f commit 8503c34
Showing 1 changed file with 16 additions and 4 deletions.
20 changes: 16 additions & 4 deletions pkg/proxy/roundrobin.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,22 @@ func NewLoadBalancerRR() *LoadBalancerRR {
}

func (lb *LoadBalancerRR) NewService(service string, affinityType api.AffinityType, ttlMinutes int) error {
lb.lock.Lock()
defer lb.lock.Unlock()

lb.newServiceInternal(service, affinityType, ttlMinutes)
return nil
}

// This assumes that lb.lock is already held.
func (lb *LoadBalancerRR) newServiceInternal(service string, affinityType api.AffinityType, ttlMinutes int) {
if ttlMinutes == 0 {
ttlMinutes = 180 //default to 3 hours if not specified. Should 0 be unlimeted instead????
}
if _, exists := lb.serviceDtlMap[balancerKey(service)]; !exists {
lb.serviceDtlMap[balancerKey(service)] = *newAffinityPolicy(affinityType, ttlMinutes)
glog.V(4).Infof("NewService. Service does not exist. So I created it: %+v", lb.serviceDtlMap[balancerKey(service)])
}
return nil
}

// return true if this service is using some form of session affinity.
Expand Down Expand Up @@ -177,8 +185,9 @@ func removeSessionAffinityByEndpoint(lb *LoadBalancerRR, service balancerKey, en
}
}

//Loop through the valid endpoints and then the endpoints associated with the Load Balancer.
// Then remove any session affinity records that are not in both lists.
// Loop through the valid endpoints and then the endpoints associated with the Load Balancer.
// Then remove any session affinity records that are not in both lists.
// This assumes the lb.lock is held.
func updateAffinityMap(lb *LoadBalancerRR, service balancerKey, newEndpoints []string) {
allEndpoints := map[string]int{}
for _, validEndpoint := range newEndpoints {
Expand Down Expand Up @@ -213,7 +222,7 @@ func (lb *LoadBalancerRR) OnUpdate(allEndpoints []api.Endpoints) {
// On update can be called without NewService being called externally.
// to be safe we will call it here. A new service will only be created
// if one does not already exist.
lb.NewService(svcEndpoints.Name, api.AffinityTypeNone, 0)
lb.newServiceInternal(svcEndpoints.Name, api.AffinityTypeNone, 0)
lb.endpointsMap[balancerKey(svcEndpoints.Name)] = slice.ShuffleStrings(newEndpoints)

// Reset the round-robin index.
Expand All @@ -232,6 +241,9 @@ func (lb *LoadBalancerRR) OnUpdate(allEndpoints []api.Endpoints) {
}

func (lb *LoadBalancerRR) CleanupStaleStickySessions(service string) {
lb.lock.Lock()
defer lb.lock.Unlock()

ttlMinutes := lb.serviceDtlMap[balancerKey(service)].ttlMinutes
for ip, affinity := range lb.serviceDtlMap[balancerKey(service)].affinityMap {
if int(time.Now().Sub(affinity.lastUsed).Minutes()) >= ttlMinutes {
Expand Down

0 comments on commit 8503c34

Please sign in to comment.