From 63d4149cc8a6e1436cf93565ee0ca4383035e357 Mon Sep 17 00:00:00 2001 From: lbbniu Date: Fri, 13 Jan 2023 15:43:47 +0800 Subject: [PATCH] test(selector): consistent hash printNode --- .../consistenthash/consistenthash_new.go | 42 +++++++++--- .../consistenthash/consistenthash_new_test.go | 66 ++++++++++++++++++- 2 files changed, 98 insertions(+), 10 deletions(-) diff --git a/tars/selector/consistenthash/consistenthash_new.go b/tars/selector/consistenthash/consistenthash_new.go index 6d209706..f824cf93 100644 --- a/tars/selector/consistenthash/consistenthash_new.go +++ b/tars/selector/consistenthash/consistenthash_new.go @@ -119,10 +119,10 @@ func (c *ConsistentHash) FindInt32(key uint32) (endpoint.Endpoint, bool) { index := sort.Search(len(c.sortedKeys), func(x int) bool { return c.sortedKeys[x] >= key }) + if index >= len(c.sortedKeys) { index = 0 } - return c.hashRing[c.sortedKeys[index]], true } @@ -133,23 +133,19 @@ func (c *ConsistentHash) Refresh(eps []endpoint.Endpoint) { c.hashRing = make(map[uint32]endpoint.Endpoint, len(eps)) c.sortedKeys = nil for _, ep := range eps { - c.addLocked(ep) + _ = c.addLocked(ep) } - sort.Slice(c.sortedKeys, func(x int, y int) bool { - return c.sortedKeys[x] < c.sortedKeys[y] - }) + c.sort() } -// Add : add the ep to the hash ring +// Add the ep to the hash ring func (c *ConsistentHash) Add(ep endpoint.Endpoint) error { c.Lock() defer c.Unlock() if err := c.addLocked(ep); err != nil { return err } - sort.Slice(c.sortedKeys, func(x int, y int) bool { - return c.sortedKeys[x] < c.sortedKeys[y] - }) + c.sort() return nil } @@ -203,6 +199,30 @@ func (c *ConsistentHash) Remove(ep endpoint.Endpoint) error { return nil } +func (c *ConsistentHash) printNode() { + mapNode := map[string]uint32{} + // 打印哈希环 + for i, hashCode := range c.sortedKeys { + var value uint32 + if i == 0 { + value = 0xFFFFFFFF - c.sortedKeys[len(c.sortedKeys)-1] + c.sortedKeys[i] + mapNode[c.hashRing[hashCode].Host] += value + } else { + value = c.sortedKeys[i] - c.sortedKeys[i-1] + mapNode[c.hashRing[hashCode].Host] += value + } + fmt.Printf("printNode: %d|%s|%v\n", hashCode, c.hashRing[hashCode].Host, mapNode[c.hashRing[hashCode].Host]) + } + avg, sum, n := float64(100), float64(0), float64(len(mapNode)) + // 打印各个区间比例 + for host, count := range mapNode { + c := 100*float64(count)*n/0xFFFFFFFF - avg + fmt.Printf("result: %s|%d|%f\n", host, count, c) + sum += (float64(count)*100*n/0xFFFFFFFF - avg) * (float64(count)*100*n/0xFFFFFFFF - avg) + } + fmt.Printf("variance: %f, size: %d\n", sum/n, len(c.sortedKeys)) +} + func (c *ConsistentHash) weight(w int32) int { weight := c.replicates if c.enableWeight { @@ -222,6 +242,10 @@ func (c *ConsistentHash) reBuildHashRingLocked() { for vk := range c.hashRing { c.sortedKeys = append(c.sortedKeys, vk) } + c.sort() +} + +func (c *ConsistentHash) sort() { sort.Slice(c.sortedKeys, func(x, y int) bool { return c.sortedKeys[x] < c.sortedKeys[y] }) diff --git a/tars/selector/consistenthash/consistenthash_new_test.go b/tars/selector/consistenthash/consistenthash_new_test.go index 645b54f7..702f3541 100644 --- a/tars/selector/consistenthash/consistenthash_new_test.go +++ b/tars/selector/consistenthash/consistenthash_new_test.go @@ -1,6 +1,10 @@ package consistenthash -import "testing" +import ( + "testing" + + "github.com/TarsCloud/TarsGo/tars/util/endpoint" +) func TestHash(t *testing.T) { k := KetamaHashAlg{} @@ -8,3 +12,63 @@ func TestHash(t *testing.T) { d := DefaultHashAlg{} t.Log(d.Hash("1.1.1.1")) } + +func TestConsistentHash(t *testing.T) { + ch := New(false, DefaultHash) + ch.Add(endpoint.Endpoint{ + Host: "10.160.129.102", + Qos: 2, + }) + ch.Add(endpoint.Endpoint{ + Host: "10.160.129.105", + Qos: 1, + }) + ch.printNode() + ep, _ := ch.FindInt32(hashFn("#12723353")) + t.Log("#12723353", hashFn("#12723353"), ep.Host) + ep, _ = ch.FindInt32(hashFn("#12723353_native")) + t.Log("#12723353_native", hashFn("#12723353_native"), ep.Host) +} + +func TestKetamaHashAlg_Hash(t *testing.T) { + tests := []struct { + name string + str string + want uint32 + }{ + { + name: "1.1.1.1", + str: "1.1.1.1", + want: 329942752, + }, + { + name: "2.2.2.2", + str: "2.2.2.2", + want: 329942752, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + k := KetamaHashAlg{} + if code := k.Hash(tt.str); code != tt.want { + t.Errorf("Hash() = %v, want %v", code, tt.want) + } + }) + } +} + +func hashFn(str string) uint32 { + var value uint32 + for _, c := range str { + value += uint32(c) + value += value << 10 + value ^= value >> 6 + } + value += value << 3 + value ^= value >> 11 + value += value << 15 + if value == 0 { + return 1 + } + return value +}