隨機(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é)點約定的權(quán)重
currentWeight int //節(jié)點臨時權(quán)重,每輪都會變化
effectiveWeight int //有效權(quán)重, 默認(rèn)與weight相同 , totalWeight = sum(effectiveWeight) //出現(xiàn)故障就-1
}
//1, currentWeight = currentWeight + effectiveWeight
//2, 選中最大的currentWeight節(jié)點為選中節(jié)點
//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 計算所有有效權(quán)重
total += w.effectiveWeight
//2 修改當(dāng)前節(jié)點臨時權(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é)點
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é)點hash切片
hashMap map[uint32]string //節(jié)點哈希和key的map, 鍵是hash值,值是節(jié)點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é)點,參數(shù)為節(jié)點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ù)制因子計算所有虛擬節(jié)點的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é)點的哈希值進(jìn)行排序,方便之后進(jìn)行二分查找
sort.Sort(c.keys)
return nil
}
// Get 方法根據(jù)給定的對象獲取最靠近它的那個節(jié)點
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é)點,第一個"服務(wù)器hash"值大于"數(shù)據(jù)hash"值的就是最優(yōu)"服務(wù)器節(jié)點"
idx := sort.Search(len(c.keys), func(i int) bool { return c.keys[i] >= hash })
// 如果查找結(jié)果 大于 服務(wù)器節(jié)點哈希數(shù)組的最大索引,表示此時該對象哈希值位于最后一個節(jié)點之后,那么放入第一個節(jié)點中
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實現(xiàn)四種負(fù)載均衡的算法(隨機(jī),輪詢等)的文章就介紹到這了,更多相關(guān)Golang 負(fù)載均衡內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- golang grpc 負(fù)載均衡的方法
- 使用Golang實現(xiàn)加權(quán)負(fù)載均衡算法的實現(xiàn)代碼