Skip to content

Commit a65bfbf

Browse files
Reduce useless migrations based on connection count in short connection workload (#802) (#803)
Co-authored-by: djshow832 <[email protected]>
1 parent 6e5a872 commit a65bfbf

File tree

2 files changed

+72
-6
lines changed

2 files changed

+72
-6
lines changed

pkg/balance/factor/factor_conn.go

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,18 @@ const (
1212
// connBalancedRatio is the threshold of ratio of the most connection count and least count.
1313
// If the ratio exceeds the threshold, we migrate connections.
1414
connBalancedRatio = 1.2
15-
// balanceCount4Conn indicates how many connections to balance per second.
16-
// Migrate slowly because we don't know the CPU usage here and we may migrate too many connections.
17-
balanceCount4Conn = 1
15+
// Narrow it to 20% in 120s, but the speed is slower and slower because the difference is getting smaller.
16+
// The original difference is 30%: after 120s, the difference is 23.5%.
17+
// The original difference is 100%: after 120s, the difference is 43.9%.
18+
balanceSeconds4Conn = 120
1819
)
1920

2021
var _ Factor = (*FactorConnCount)(nil)
2122

23+
// FactorConnCount balances by connection count and must be used in following cases:
24+
// - The policy is set to `connection`
25+
// - The backend CPU usages are unavailable
26+
// - The workload just starts and the backend CPU usages are low
2227
type FactorConnCount struct {
2328
bitNum int
2429
}
@@ -50,10 +55,15 @@ func (fcc *FactorConnCount) ScoreBitNum() int {
5055
}
5156

5257
func (fcc *FactorConnCount) BalanceCount(from, to scoredBackend) (float64, []zap.Field) {
53-
if float64(from.ConnScore()) > float64(to.ConnScore()+1)*connBalancedRatio {
54-
return balanceCount4Conn, nil
58+
if float64(from.ConnScore()) <= float64(to.ConnScore()+1)*connBalancedRatio {
59+
return 0, nil
5560
}
56-
return 0, nil
61+
targetTo := float64(from.ConnScore()+to.ConnScore()+1) / (1 + connBalancedRatio)
62+
count := (targetTo - float64(to.ConnScore()+1)) / balanceSeconds4Conn
63+
if count < 0 {
64+
count = 0
65+
}
66+
return count, nil
5767
}
5868

5969
func (fcc *FactorConnCount) SetConfig(cfg *config.Config) {

pkg/balance/factor/factor_conn_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,59 @@ func TestFactorConnCount(t *testing.T) {
3838
require.Equal(t, test.expectedScore, backends[i].score(), "test idx: %d", i)
3939
}
4040
}
41+
42+
func TestFactorConnSpeed(t *testing.T) {
43+
tests := []struct {
44+
score1 int
45+
score2 int
46+
targetRange [2]int
47+
}{
48+
{
49+
score1: 120,
50+
score2: 100,
51+
targetRange: [2]int{100, 100},
52+
},
53+
{
54+
score1: 150,
55+
score2: 100,
56+
targetRange: [2]int{110, 114},
57+
},
58+
{
59+
score1: 10000,
60+
score2: 0,
61+
targetRange: [2]int{3500, 4550},
62+
},
63+
}
64+
65+
factor := NewFactorConnCount()
66+
backend1 := newMockBackend(true, 0)
67+
backend2 := newMockBackend(true, 0)
68+
scoredBackend1 := newScoredBackend(backend1, zap.NewNop())
69+
scoredBackend2 := newScoredBackend(backend2, zap.NewNop())
70+
for i, test := range tests {
71+
backend1.connScore = test.score1
72+
backend2.connScore = test.score2
73+
lastRedirectTime := 0
74+
// Simulate rebalance for 5 minutes.
75+
for j := 0; j < 30000; j++ {
76+
balanceCount, _ := factor.BalanceCount(scoredBackend1, scoredBackend2)
77+
if balanceCount < 0.0001 {
78+
break
79+
}
80+
migrationInterval := 100 / balanceCount
81+
count := 0
82+
if migrationInterval < 2 {
83+
count = int(1 / migrationInterval)
84+
} else if float64(j-lastRedirectTime) >= migrationInterval {
85+
count = 1
86+
}
87+
if count > 0 {
88+
lastRedirectTime = j
89+
backend1.connScore -= count
90+
backend2.connScore += count
91+
}
92+
}
93+
require.GreaterOrEqual(t, backend2.connScore, test.targetRange[0], "case id: %d", i)
94+
require.LessOrEqual(t, backend2.connScore, test.targetRange[1], "case id: %d", i)
95+
}
96+
}

0 commit comments

Comments
 (0)