-
Notifications
You must be signed in to change notification settings - Fork 759
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #120 from domgoer/master
fix: use unsupported loadbalance will cause nil pointer
- Loading branch information
Showing
12 changed files
with
3,183 additions
and
841 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package lb | ||
|
||
import ( | ||
"container/list" | ||
"github.com/fagongzi/gateway/pkg/pb/metapb" | ||
"github.com/valyala/fasthttp" | ||
) | ||
|
||
// WeightRobin weight robin loadBalance impl | ||
type WeightRobin struct { | ||
opts map[uint64]*weightRobin | ||
} | ||
|
||
// weightRobin used to save the weight info of server | ||
type weightRobin struct { | ||
effectiveWeight int64 | ||
currentWeight int64 | ||
} | ||
|
||
// NewWeightRobin create a WeightRobin | ||
func NewWeightRobin() LoadBalance { | ||
return &WeightRobin{ | ||
opts: make(map[uint64]*weightRobin, 1024), | ||
} | ||
} | ||
|
||
// Select select a server from servers using WeightRobin | ||
func (w *WeightRobin) Select(req *fasthttp.Request, servers *list.List) (best uint64) { | ||
var total int64 | ||
|
||
for iter := servers.Back(); iter != nil; iter = iter.Prev() { | ||
svr := iter.Value.(*metapb.Server) | ||
|
||
id := svr.ID | ||
if _, ok := w.opts[id]; !ok { | ||
w.opts[id] = &weightRobin{ | ||
effectiveWeight: svr.Weight, | ||
} | ||
} | ||
|
||
wt := w.opts[id] | ||
wt.currentWeight += wt.effectiveWeight | ||
total += wt.effectiveWeight | ||
|
||
if wt.effectiveWeight < svr.Weight { | ||
wt.effectiveWeight++ | ||
} | ||
|
||
if best == 0 || w.opts[uint64(best)] == nil || wt.currentWeight > w.opts[best].currentWeight { | ||
best = id | ||
} | ||
} | ||
|
||
if best == 0 { | ||
return 0 | ||
} | ||
|
||
w.opts[best].currentWeight -= total | ||
|
||
return best | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package lb | ||
|
||
import ( | ||
"container/list" | ||
"github.com/fagongzi/gateway/pkg/pb/metapb" | ||
"github.com/valyala/fasthttp" | ||
"testing" | ||
) | ||
|
||
func TestWeightRobin_Select(t *testing.T) { | ||
li := list.New() | ||
|
||
li.PushBack(&metapb.Server{ | ||
ID: 1, | ||
Weight: 20, | ||
}) | ||
li.PushBack(&metapb.Server{ | ||
ID: 2, | ||
Weight: 10, | ||
}) | ||
li.PushBack(&metapb.Server{ | ||
ID: 3, | ||
Weight: 35, | ||
}) | ||
li.PushBack(&metapb.Server{ | ||
ID: 4, | ||
Weight: 5, | ||
}) | ||
|
||
type fields struct { | ||
opts map[uint64]*weightRobin | ||
} | ||
type args struct { | ||
req *fasthttp.Request | ||
servers *list.List | ||
} | ||
tests := []struct { | ||
name string | ||
fields fields | ||
args args | ||
wantBest []int | ||
}{ | ||
{ | ||
name: "test_case_1", | ||
fields: struct{ opts map[uint64]*weightRobin }{opts: make(map[uint64]*weightRobin, 50)}, | ||
args: struct { | ||
req *fasthttp.Request | ||
servers *list.List | ||
}{req: nil, servers: li}, | ||
wantBest: []int{20, 10, 35, 5}, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
var res = make(map[uint64]int) | ||
t.Run(tt.name, func(t *testing.T) { | ||
w := &WeightRobin{ | ||
opts: tt.fields.opts, | ||
} | ||
for i := 0; i < 70; i++ { | ||
res[w.Select(tt.args.req, tt.args.servers)]++ | ||
} | ||
}) | ||
for k, v := range res { | ||
if tt.wantBest[k-1] != v { | ||
t.Errorf("WeightRobin.Select() = %v, want %v", res, tt.wantBest) | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.