Skip to content

Commit 338a0c2

Browse files
authored
Merge pull request #73 from sanxun0325/weight_election
update weight election
2 parents ad48443 + 0d062ab commit 338a0c2

File tree

4 files changed

+323
-19
lines changed

4 files changed

+323
-19
lines changed

clients/naming_client/naming_client.go

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"math"
1313
"math/rand"
1414
"os"
15+
"sort"
1516
"strings"
1617
"time"
1718
)
@@ -25,6 +26,12 @@ type NamingClient struct {
2526
indexMap cache.ConcurrentMap
2627
}
2728

29+
type Chooser struct {
30+
data []model.Instance
31+
totals []int
32+
max int
33+
}
34+
2835
func NewNamingClient(nc nacos_client.INacosClient) (NamingClient, error) {
2936
naming := NamingClient{}
3037
clientConfig, err :=
@@ -190,23 +197,9 @@ func (sc *NamingClient) selectOneHealthyInstances(service model.Service) (*model
190197
return nil, errors.New("healthy instance list is empty!")
191198
}
192199

193-
randomInstances := random(result, mw)
194-
key := utils.GetServiceCacheKey(service.Name, service.Clusters)
195-
i, indexOk := sc.indexMap.Get(key)
196-
var index int
197-
198-
if !indexOk {
199-
index = rand.Intn(len(randomInstances))
200-
} else {
201-
index = i.(int)
202-
index += 1
203-
if index >= len(randomInstances) {
204-
index = index % len(randomInstances)
205-
}
206-
}
207-
208-
sc.indexMap.Set(key, index)
209-
return &randomInstances[index], nil
200+
chooser := newChooser(result)
201+
instance := chooser.pick()
202+
return &instance, nil
210203
}
211204

212205
func random(instances []model.Instance, mw int) []model.Instance {
@@ -225,6 +218,38 @@ func random(instances []model.Instance, mw int) []model.Instance {
225218
return result
226219
}
227220

221+
type instance []model.Instance
222+
223+
func (a instance) Len() int {
224+
return len(a)
225+
}
226+
227+
func (a instance) Swap(i, j int) {
228+
a[i], a[j] = a[j], a[i]
229+
}
230+
231+
func (a instance) Less(i, j int) bool {
232+
return a[i].Weight < a[j].Weight
233+
}
234+
235+
// NewChooser initializes a new Chooser for picking from the provided Choices.
236+
func newChooser(instances []model.Instance) Chooser {
237+
sort.Sort(instance(instances))
238+
totals := make([]int, len(instances))
239+
runningTotal := 0
240+
for i, c := range instances {
241+
runningTotal += int(c.Weight)
242+
totals[i] = runningTotal
243+
}
244+
return Chooser{data: instances, totals: totals, max: runningTotal}
245+
}
246+
247+
func (chs Chooser) pick() model.Instance {
248+
r := rand.Intn(chs.max) + 1
249+
i := sort.SearchInts(chs.totals, r)
250+
return chs.data[i]
251+
}
252+
228253
// 服务监听
229254
func (sc *NamingClient) Subscribe(param *vo.SubscribeParam) error {
230255
if param.GroupName == "" {

clients/naming_client/naming_client_test.go

Lines changed: 279 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ func TestNamingClient_SelectOneHealthyInstance_SameWeight(t *testing.T) {
442442
Weight: 1,
443443
Metadata: map[string]string{},
444444
ClusterName: "a",
445-
ServiceName: "DEMO",
445+
ServiceName: "DEMO1",
446446
Enable: true,
447447
Healthy: true,
448448
},
@@ -770,5 +770,282 @@ func TestNamingClient_GetAllServicesInfo(t *testing.T) {
770770
GroupName: "DEFAULT_GROUP",
771771
})
772772
fmt.Println(len(reslut))
773-
assert.NotNil(t, err)
773+
assert.Equal(t, err == nil, true)
774+
assert.Equal(t, 0, len(reslut))
775+
}
776+
777+
func TestNamingClient_selectOneHealthyInstanceResult(t *testing.T) {
778+
services := model.Service(model.Service{
779+
Name: "DEFAULT_GROUP@@DEMO",
780+
Hosts: []model.Instance{
781+
{
782+
Ip: "127.0.0.1",
783+
Weight: 1,
784+
Enable: true,
785+
Healthy: true,
786+
},
787+
{
788+
Ip: "127.0.0.2",
789+
Weight: 9,
790+
Enable: true,
791+
Healthy: true,
792+
},
793+
}})
794+
nc := nacos_client.NacosClient{}
795+
nc.SetServerConfig([]constant.ServerConfig{serverConfigTest})
796+
nc.SetClientConfig(clientConfigTest)
797+
client, _ := NewNamingClient(&nc)
798+
for i := 0; i < 10; i++ {
799+
i,_:=client.selectOneHealthyInstances(services)
800+
fmt.Println(i.Ip)
801+
}
802+
}
803+
804+
func BenchmarkNamingClient_SelectOneHealthyInstances(b *testing.B) {
805+
services := model.Service(model.Service{
806+
Name: "DEFAULT_GROUP@@DEMO",
807+
CacheMillis: 1000,
808+
UseSpecifiedURL: false,
809+
Hosts: []model.Instance{
810+
{
811+
Valid: true,
812+
Marked: false,
813+
InstanceId: "10.10.10.10-80-a-DEMO",
814+
Port: 80,
815+
Ip: "10.10.10.10",
816+
Weight: 10,
817+
Metadata: map[string]string{},
818+
ClusterName: "a",
819+
ServiceName: "DEMO1",
820+
Enable: true,
821+
Healthy: true,
822+
},
823+
{
824+
Valid: true,
825+
Marked: false,
826+
InstanceId: "10.10.10.11-80-a-DEMO",
827+
Port: 80,
828+
Ip: "10.10.10.11",
829+
Weight: 10,
830+
Metadata: map[string]string{},
831+
ClusterName: "a",
832+
ServiceName: "DEMO2",
833+
Enable: true,
834+
Healthy: true,
835+
},
836+
{
837+
Valid: true,
838+
Marked: false,
839+
InstanceId: "10.10.10.12-80-a-DEMO",
840+
Port: 80,
841+
Ip: "10.10.10.12",
842+
Weight: 1,
843+
Metadata: map[string]string{},
844+
ClusterName: "a",
845+
ServiceName: "DEMO3",
846+
Enable: true,
847+
Healthy: false,
848+
},
849+
{
850+
Valid: true,
851+
Marked: false,
852+
InstanceId: "10.10.10.13-80-a-DEMO",
853+
Port: 80,
854+
Ip: "10.10.10.13",
855+
Weight: 1,
856+
Metadata: map[string]string{},
857+
ClusterName: "a",
858+
ServiceName: "DEMO4",
859+
Enable: false,
860+
Healthy: true,
861+
},
862+
{
863+
Valid: true,
864+
Marked: false,
865+
InstanceId: "10.10.10.14-80-a-DEMO",
866+
Port: 80,
867+
Ip: "10.10.10.14",
868+
Weight: 0,
869+
Metadata: map[string]string{},
870+
ClusterName: "a",
871+
ServiceName: "DEMO5",
872+
Enable: true,
873+
Healthy: true,
874+
},
875+
},
876+
Checksum: "3bbcf6dd1175203a8afdade0e77a27cd1528787794594",
877+
LastRefTime: 1528787794594, Env: "", Clusters: "a",
878+
Metadata: map[string]string(nil)})
879+
nc := nacos_client.NacosClient{}
880+
nc.SetServerConfig([]constant.ServerConfig{serverConfigTest})
881+
nc.SetClientConfig(clientConfigTest)
882+
client, _ := NewNamingClient(&nc)
883+
b.ResetTimer()
884+
for i := 0; i < b.N; i++ {
885+
client.selectOneHealthyInstances(services)
886+
}
887+
888+
}
889+
890+
func BenchmarkNamingClient_Random(b *testing.B) {
891+
services := model.Service(model.Service{
892+
Name: "DEFAULT_GROUP@@DEMO",
893+
CacheMillis: 1000,
894+
UseSpecifiedURL: false,
895+
Hosts: []model.Instance{
896+
{
897+
Valid: true,
898+
Marked: false,
899+
InstanceId: "10.10.10.10-80-a-DEMO",
900+
Port: 80,
901+
Ip: "10.10.10.10",
902+
Weight: 10,
903+
Metadata: map[string]string{},
904+
ClusterName: "a",
905+
ServiceName: "DEMO1",
906+
Enable: true,
907+
Healthy: true,
908+
},
909+
{
910+
Valid: true,
911+
Marked: false,
912+
InstanceId: "10.10.10.11-80-a-DEMO",
913+
Port: 80,
914+
Ip: "10.10.10.11",
915+
Weight: 9,
916+
Metadata: map[string]string{},
917+
ClusterName: "a",
918+
ServiceName: "DEMO",
919+
Enable: true,
920+
Healthy: true,
921+
},
922+
{
923+
Valid: true,
924+
Marked: false,
925+
InstanceId: "10.10.10.12-80-a-DEMO",
926+
Port: 80,
927+
Ip: "10.10.10.12",
928+
Weight: 8,
929+
Metadata: map[string]string{},
930+
ClusterName: "a",
931+
ServiceName: "DEMO",
932+
Enable: true,
933+
Healthy: false,
934+
},
935+
{
936+
Valid: true,
937+
Marked: false,
938+
InstanceId: "10.10.10.13-80-a-DEMO",
939+
Port: 80,
940+
Ip: "10.10.10.13",
941+
Weight: 8,
942+
Metadata: map[string]string{},
943+
ClusterName: "a",
944+
ServiceName: "DEMO",
945+
Enable: false,
946+
Healthy: true,
947+
},
948+
{
949+
Valid: true,
950+
Marked: false,
951+
InstanceId: "10.10.10.14-80-a-DEMO",
952+
Port: 80,
953+
Ip: "10.10.10.14",
954+
Weight: 7,
955+
Metadata: map[string]string{},
956+
ClusterName: "a",
957+
ServiceName: "DEMO",
958+
Enable: true,
959+
Healthy: true,
960+
},
961+
},
962+
Checksum: "3bbcf6dd1175203a8afdade0e77a27cd1528787794594",
963+
LastRefTime: 1528787794594, Env: "", Clusters: "a",
964+
Metadata: map[string]string(nil)})
965+
b.ResetTimer()
966+
for i := 0; i < b.N; i++ {
967+
random(services.Hosts, 10)
968+
}
969+
}
970+
971+
func BenchmarkNamingClient_ChooserPick(b *testing.B) {
972+
services := model.Service(model.Service{
973+
Name: "DEFAULT_GROUP@@DEMO",
974+
CacheMillis: 1000,
975+
UseSpecifiedURL: false,
976+
Hosts: []model.Instance{
977+
{
978+
Valid: true,
979+
Marked: false,
980+
InstanceId: "10.10.10.10-80-a-DEMO",
981+
Port: 80,
982+
Ip: "10.10.10.10",
983+
Weight: 10,
984+
Metadata: map[string]string{},
985+
ClusterName: "a",
986+
ServiceName: "DEMO1",
987+
Enable: true,
988+
Healthy: true,
989+
},
990+
{
991+
Valid: true,
992+
Marked: false,
993+
InstanceId: "10.10.10.11-80-a-DEMO",
994+
Port: 80,
995+
Ip: "10.10.10.11",
996+
Weight: 9,
997+
Metadata: map[string]string{},
998+
ClusterName: "a",
999+
ServiceName: "DEMO",
1000+
Enable: true,
1001+
Healthy: true,
1002+
},
1003+
{
1004+
Valid: true,
1005+
Marked: false,
1006+
InstanceId: "10.10.10.12-80-a-DEMO",
1007+
Port: 80,
1008+
Ip: "10.10.10.12",
1009+
Weight: 8,
1010+
Metadata: map[string]string{},
1011+
ClusterName: "a",
1012+
ServiceName: "DEMO",
1013+
Enable: true,
1014+
Healthy: false,
1015+
},
1016+
{
1017+
Valid: true,
1018+
Marked: false,
1019+
InstanceId: "10.10.10.13-80-a-DEMO",
1020+
Port: 80,
1021+
Ip: "10.10.10.13",
1022+
Weight: 7,
1023+
Metadata: map[string]string{},
1024+
ClusterName: "a",
1025+
ServiceName: "DEMO",
1026+
Enable: false,
1027+
Healthy: true,
1028+
},
1029+
{
1030+
Valid: true,
1031+
Marked: false,
1032+
InstanceId: "10.10.10.14-80-a-DEMO",
1033+
Port: 80,
1034+
Ip: "10.10.10.14",
1035+
Weight: 6,
1036+
Metadata: map[string]string{},
1037+
ClusterName: "a",
1038+
ServiceName: "DEMO",
1039+
Enable: true,
1040+
Healthy: true,
1041+
},
1042+
},
1043+
Checksum: "3bbcf6dd1175203a8afdade0e77a27cd1528787794594",
1044+
LastRefTime: 1528787794594, Env: "", Clusters: "a",
1045+
Metadata: map[string]string(nil)})
1046+
b.ResetTimer()
1047+
for i := 0; i < b.N; i++ {
1048+
chooser := newChooser(services.Hosts)
1049+
chooser.pick()
1050+
}
7741051
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ require (
1919
github.com/stretchr/testify v1.5.1
2020
github.com/tebeka/strftime v0.1.3 // indirect
2121
github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3
22+
github.com/valyala/fastrand v1.0.0
2223
)

go.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ github.com/tebeka/strftime v0.1.3 h1:5HQXOqWKYRFfNyBMNVc9z5+QzuBtIXy03psIhtdJYto
5555
github.com/tebeka/strftime v0.1.3/go.mod h1:7wJm3dZlpr4l/oVK0t1HYIc4rMzQ2XJlOMIUJUJH6XQ=
5656
github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3 h1:kF/7m/ZU+0D4Jj5eZ41Zm3IH/J8OElK1Qtd7tVKAwLk=
5757
github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3/go.mod h1:QDlpd3qS71vYtakd2hmdpqhJ9nwv6mD6A30bQ1BPBFE=
58+
github.com/valyala/fastrand v1.0.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ=
5859
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
5960
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
6061
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=

0 commit comments

Comments
 (0)