Golang實(shí)現(xiàn)四種負(fù)載均衡的算法(隨機(jī),輪詢等)
隨機(jī)負(fù)載
隨機(jī)挑選目標(biāo)服務(wù)器
package load_balance import ( "errors" "math/rand" ) //隨機(jī)負(fù)載均衡 type RandomBalance struct { curIndex int rss []string } func (r *RandomBalance) Add(params ...string) error { if len(params) == 0 { return errors.New("params len 1 at least") } addr := params[0] r.rss = append(r.rss, addr) return nil } func (r *RandomBalance) Next() string { if len(r.rss) == 0 { return "" } r.curIndex = rand.Intn(len(r.rss)) return r.rss[r.curIndex] } func (r *RandomBalance) Get(string) (string, error) { return r.Next(), nil }
輪詢負(fù)載
服務(wù)器依次輪詢
package load_balance import "errors" //輪詢負(fù)載均衡 type RoundRobinBalance struct { curIndex int rss []string } func (r *RoundRobinBalance) Add(params ...string) error { if len(params) == 0 { return errors.New("params len 1 at least") } addr := params[0] r.rss = append(r.rss, addr) return nil } func (r *RoundRobinBalance) Next() string { if len(r.rss) == 0 { return "" } lens := len(r.rss) if r.curIndex >= lens { r.curIndex = 0 } curAddr := r.rss[r.curIndex] r.curIndex = (r.curIndex + 1) % lens return curAddr } func (r *RoundRobinBalance) Get(string) (string, error) { return r.Next(), nil }
加權(quán)輪詢負(fù)載
給目標(biāo)設(shè)置訪問權(quán)重,按照權(quán)重輪詢
package load_balance import ( "errors" "strconv" ) type WeightRoundRobinBalance struct { curIndex int rss []*WeightNode rsw []int } type WeightNode struct { addr string Weight int //初始化時對節(jié)點(diǎn)約定的權(quán)重 currentWeight int //節(jié)點(diǎn)臨時權(quán)重,每輪都會變化 effectiveWeight int //有效權(quán)重, 默認(rèn)與weight相同 , totalWeight = sum(effectiveWeight) //出現(xiàn)故障就-1 } //1, currentWeight = currentWeight + effectiveWeight //2, 選中最大的currentWeight節(jié)點(diǎn)為選中節(jié)點(diǎn) //3, currentWeight = currentWeight - totalWeight func (r *WeightRoundRobinBalance) Add(params ...string) error { if len(params) != 2 { return errors.New("params len need 2") } parInt, err := strconv.ParseInt(params[1], 10, 64) if err != nil { return err } node := &WeightNode{ addr: params[0], Weight: int(parInt), } node.effectiveWeight = node.Weight r.rss = append(r.rss, node) return nil } func (r *WeightRoundRobinBalance) Next() string { var best *WeightNode total := 0 for i := 0; i < len(r.rss); i++ { w := r.rss[i] //1 計(jì)算所有有效權(quán)重 total += w.effectiveWeight //2 修改當(dāng)前節(jié)點(diǎn)臨時權(quán)重 w.currentWeight += w.effectiveWeight //3 有效權(quán)重默認(rèn)與權(quán)重相同,通訊異常時-1, 通訊成功+1,直到恢復(fù)到weight大小 if w.effectiveWeight < w.Weight { w.effectiveWeight++ } //4 選中最大臨時權(quán)重節(jié)點(diǎn) if best == nil || w.currentWeight > best.currentWeight { best = w } } if best == nil { return "" } //5 變更臨時權(quán)重為 臨時權(quán)重-有效權(quán)重之和 best.currentWeight -= total return best.addr } func (r *WeightRoundRobinBalance) Get(string) (string, error) { return r.Next(), nil } func (r *WeightRoundRobinBalance) Update() { }
一致性hash
請求固定的URL訪問指定的IP
package load_balance import ( "errors" "hash/crc32" "sort" "strconv" "sync" ) //1 單調(diào)性(唯一) 2平衡性 (數(shù)據(jù) 目標(biāo)元素均衡) 3分散性(散列) type Hash func(data []byte) uint32 type UInt32Slice []uint32 func (s UInt32Slice) Len() int { return len(s) } func (s UInt32Slice) Less(i, j int) bool { return s[i] < s[j] } func (s UInt32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } type ConsistentHashBalance struct { mux sync.RWMutex hash Hash replicas int //復(fù)制因子 keys UInt32Slice //已排序的節(jié)點(diǎn)hash切片 hashMap map[uint32]string //節(jié)點(diǎn)哈希和key的map, 鍵是hash值,值是節(jié)點(diǎn)key } func NewConsistentHashBalance(replicas int, fn Hash) *ConsistentHashBalance { m := &ConsistentHashBalance{ replicas: replicas, hash: fn, hashMap: make(map[uint32]string), } if m.hash == nil { //最多32位,保證是一個2^32-1環(huán) m.hash = crc32.ChecksumIEEE } return m } func (c *ConsistentHashBalance) IsEmpty() bool { return len(c.keys) == 0 } // Add 方法用來添加緩存節(jié)點(diǎn),參數(shù)為節(jié)點(diǎn)key,比如使用IP func (c *ConsistentHashBalance) Add(params ...string) error { if len(params) == 0 { return errors.New("param len 1 at least") } addr := params[0] c.mux.Lock() defer c.mux.Unlock() // 結(jié)合復(fù)制因子計(jì)算所有虛擬節(jié)點(diǎn)的hash值,并存入m.keys中,同時在m.hashMap中保存哈希值和key的映射 for i := 0; i < c.replicas; i++ { hash := c.hash([]byte(strconv.Itoa(i) + addr)) c.keys = append(c.keys, hash) c.hashMap[hash] = addr } // 對所有虛擬節(jié)點(diǎn)的哈希值進(jìn)行排序,方便之后進(jìn)行二分查找 sort.Sort(c.keys) return nil } // Get 方法根據(jù)給定的對象獲取最靠近它的那個節(jié)點(diǎn) func (c *ConsistentHashBalance) Get(key string) (string, error) { if c.IsEmpty() { return "", errors.New("node is empty") } hash := c.hash([]byte(key)) // 通過二分查找獲取最優(yōu)節(jié)點(diǎn),第一個"服務(wù)器hash"值大于"數(shù)據(jù)hash"值的就是最優(yōu)"服務(wù)器節(jié)點(diǎn)" idx := sort.Search(len(c.keys), func(i int) bool { return c.keys[i] >= hash }) // 如果查找結(jié)果 大于 服務(wù)器節(jié)點(diǎn)哈希數(shù)組的最大索引,表示此時該對象哈希值位于最后一個節(jié)點(diǎn)之后,那么放入第一個節(jié)點(diǎn)中 if idx == len(c.keys) { idx = 0 } c.mux.RLock() defer c.mux.RUnlock() return c.hashMap[c.keys[idx]], nil }
封裝
定義LoadBalance接口
package load_balance type LoadBalance interface { Add(...string) error Get(string)(string, error) }
工廠方法
package load_balance type LbType int const ( LbRandom LbType = iota LbRoundRobin LbWeightRoundRobin LbConsistentHash ) func LoadBalanceFactory(lbType LbType) LoadBalance { switch lbType { case LbRandom: return &RandomBalance{} case LbConsistentHash: return NewConsistentHashBalance(10, nil) case LbRoundRobin: return &RoundRobinBalance{} case LbWeightRoundRobin: return &WeightRoundRobinBalance{} default: return &RandomBalance{} } }
到此這篇關(guān)于Golang實(shí)現(xiàn)四種負(fù)載均衡的算法(隨機(jī),輪詢等)的文章就介紹到這了,更多相關(guān)Golang 負(fù)載均衡內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go打印結(jié)構(gòu)體提升代碼調(diào)試效率實(shí)例詳解
這篇文章主要介紹了Go打印結(jié)構(gòu)體提升代碼調(diào)試效率實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-02-02Go 語言數(shù)據(jù)結(jié)構(gòu)之雙鏈表學(xué)習(xí)教程
這篇文章主要為大家介紹了Go 語言數(shù)據(jù)結(jié)構(gòu)之雙鏈表學(xué)習(xí)教程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08Go用兩個協(xié)程交替打印100以內(nèi)的奇偶數(shù)的方法詳解
這篇文章主要給大家詳細(xì)介紹了Go用兩個協(xié)程交替打印100以內(nèi)的奇偶數(shù)的示例代碼,文中給大家介紹了兩個實(shí)現(xiàn)方法,使用無緩沖的channel和設(shè)置GOMAXPROCS=1,介紹的非常詳細(xì),需要的朋友可以參考下2023-08-08