Skip to content

Commit 8ab1e52

Browse files
committed
fix: LB handling non /invoke requests
1 parent e7f6dbb commit 8ab1e52

3 files changed

Lines changed: 50 additions & 10 deletions

File tree

internal/lb/architectureAwareLb.go

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ type ArchitectureAwareBalancer struct {
2424
armRing *HashRing
2525
x86Ring *HashRing
2626

27-
mode string
28-
rrIndices map[string]int
27+
mode string
28+
archRRIndex int
29+
armRRIndex int // for non-invoke requests using RR
30+
x86RRIndex int // for non-invoke requests using RR
2931
}
3032

3133
// NewArchitectureAwareBalancer Constructor
@@ -37,9 +39,11 @@ func NewArchitectureAwareBalancer(targets []*middleware.ProxyTarget) *Architectu
3739
log.Printf("Running ArchitectureAwareLB with %d replicas per node in the hash rings\n", REPLICAS)
3840

3941
b := &ArchitectureAwareBalancer{
40-
armRing: NewHashRing(REPLICAS),
41-
x86Ring: NewHashRing(REPLICAS),
42-
rrIndices: make(map[string]int),
42+
armRing: NewHashRing(REPLICAS),
43+
x86Ring: NewHashRing(REPLICAS),
44+
archRRIndex: 0,
45+
armRRIndex: 0,
46+
x86RRIndex: 0,
4347
}
4448

4549
b.mode = config.GetString(config.LB_MODE, RR)
@@ -64,6 +68,26 @@ func (b *ArchitectureAwareBalancer) Next(c echo.Context) *middleware.ProxyTarget
6468
b.mu.Lock()
6569
defer b.mu.Unlock()
6670

71+
if !isInvoke(c) {
72+
// fallback to round-robin
73+
var candidate *middleware.ProxyTarget
74+
var arch string
75+
if len(b.armRing.targetList) > 0 {
76+
arch = b.selectArchitectureRR()
77+
} else {
78+
arch = container.X86
79+
}
80+
81+
if arch == container.ARM {
82+
b.armRRIndex = (b.armRRIndex + 1) % len(b.armRing.targetList)
83+
candidate = b.armRing.targetList[b.armRRIndex]
84+
} else {
85+
b.x86RRIndex = (b.x86RRIndex + 1) % len(b.x86Ring.targetList)
86+
candidate = b.x86Ring.targetList[b.x86RRIndex]
87+
}
88+
return candidate
89+
}
90+
6791
funcName := extractFunctionName(c) // get function's name from request's URL
6892
fun, ok := function.GetFunction(funcName) // we use this to leverage cache before asking etcd
6993
if !ok {
@@ -88,7 +112,7 @@ func (b *ArchitectureAwareBalancer) Next(c echo.Context) *middleware.ProxyTarget
88112
bandit := mab.GlobalBanditManager.GetBandit(funcName)
89113
targetArch = bandit.SelectArm(ctx)
90114
} else if b.mode == RR { // RoundRobin
91-
targetArch = b.selectArchitectureRR(funcName) // here the load balancer decides what architecture to use for this function
115+
targetArch = b.selectArchitectureRR() // here the load balancer decides what architecture to use for this function
92116
} else { // Random
93117
targetArch = b.selectArchitectureRandom() // random load balancer for testing purposes
94118
}
@@ -196,14 +220,14 @@ func (b *ArchitectureAwareBalancer) selectArchitecture(fun *function.Function) (
196220
}
197221

198222
// selectArchitectureRR selects the architecture using a Round Robin policy.
199-
func (b *ArchitectureAwareBalancer) selectArchitectureRR(funcName string) string {
223+
func (b *ArchitectureAwareBalancer) selectArchitectureRR() string {
200224

201225
// This is just a function to use as a baseline for the LB. It should actually implement checks over the rings dimension.
202226
// i.e.: it cannot select ARM/X86 "blindly", it should check if we have at least one node for that architecture.
203227
archs := []string{container.ARM, container.X86}
204-
index := b.rrIndices[funcName]
228+
index := b.archRRIndex
205229
selected := archs[index]
206-
b.rrIndices[funcName] = (index + 1) % len(archs)
230+
b.archRRIndex = (index + 1) % len(archs)
207231
return selected
208232
}
209233

internal/lb/architectureUnawareLb.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package lb
22

33
import (
44
"log"
5+
"strings"
56
"sync"
67
"time"
78

@@ -18,6 +19,9 @@ type ArchitectureUnawareBalancer struct {
1819

1920
// instead of classic lists we will use hashRings (see hashRing.go) to implement a consistent hashing technique
2021
hashRing *HashRing
22+
23+
// round-robin: used for non-invocation requests
24+
rrIndex int
2125
}
2226

2327
// NewArchitectureUnawareBalancer Constructor
@@ -53,6 +57,14 @@ func (b *ArchitectureUnawareBalancer) Next(c echo.Context) *middleware.ProxyTarg
5357
b.mu.Lock()
5458
defer b.mu.Unlock()
5559

60+
if !isInvoke(c) {
61+
// fallback to round-robin
62+
b.rrIndex = (b.rrIndex + 1) % len(b.hashRing.targetList)
63+
candidate := b.hashRing.targetList[b.rrIndex]
64+
log.Printf("Forwarding %s request to target %s\n", c.Path(), candidate.Name)
65+
return candidate
66+
}
67+
5668
funcName := extractFunctionName(c) // get function's name from request's URL
5769
fun, ok := function.GetFunction(funcName) // we use this to leverage cache before asking etcd
5870
if !ok {
@@ -75,6 +87,10 @@ func (b *ArchitectureUnawareBalancer) Next(c echo.Context) *middleware.ProxyTarg
7587
return candidate
7688
}
7789

90+
func isInvoke(c echo.Context) bool {
91+
return strings.HasPrefix(c.Path(), "/invoke/")
92+
}
93+
7894
// AddTarget Echo requires this method for dynamic load-balancing. It simply inserts a new node in the respective ring.
7995
func (b *ArchitectureUnawareBalancer) AddTarget(t *middleware.ProxyTarget) bool {
8096
b.mu.Lock()

internal/lb/lb.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ var currentTargets []*middleware.ProxyTarget
2424

2525
func newBalancer(targets []*middleware.ProxyTarget) (middleware.ProxyBalancer, bool) {
2626
// old Load Balancer: return middleware.NewRoundRobinBalancer(targets)
27-
isArchAware := config.GetBool(config.Arch_AWARENESS, true)
27+
isArchAware := config.GetBool(config.Arch_AWARENESS, false)
2828

2929
if isArchAware {
3030
return NewArchitectureAwareBalancer(targets), true

0 commit comments

Comments
 (0)