Golang負載均衡和?;钤O計原理示例探究
引言
通過本項目可以學到什么?
負載均衡算法代碼實現(xiàn)
調(diào)度器如何維護節(jié)點Live方案(參考)
loadbalance 負載均衡算法
隨機算法,輪詢算法,加權輪詢算法
隨機算法
// 隨機
type Rand struct {
addrs []string
}
func (r *Rand) Add(param []string) error {
iflen(param) != 1 {
return ErrParam
}
r.addrs = append(r.addrs, param[0])
returnnil
}
// 隨機種子,每次隨機返回一個
func (r *Rand) Get() (string, error) {
iflen(r.addrs) == 0 {
return"", ErrNoAddr
}
rand.Seed(time.Now().UnixNano())
idx := rand.Intn(len(r.addrs))
return r.addrs[idx], nil
}
輪詢算法
// 輪詢
type RoundRobin struct {
addrs []string
curIdx int
}
func (r *RoundRobin) Add(param []string) error {
iflen(param) != 1 {
return ErrParam
}
r.addrs = append(r.addrs, param[0])
returnnil
}
func (r *RoundRobin) Get() (string, error) {
iflen(r.addrs) == 0 || r.curIdx >= len(r.addrs) {
return"", ErrNoAddr
}
addr := r.addrs[r.curIdx]
r.curIdx = (r.curIdx + 1) % len(r.addrs) // 對curIdx每次+1
return addr, nil
}
加權輪詢算法
實現(xiàn)原理
對節(jié)點設置權重,權重越大被選中次數(shù)越高,節(jié)點被選中的次數(shù)≈(本節(jié)點權重/全部權重) * 總次數(shù)。
舉例說明:
節(jié)點權重為:weight [a=1,b=2,c=5]
節(jié)點當前權重為curWeight:初始值為[a=0,b=0,c=0],變化規(guī)則為:curWeight + weight
全部權重sumWeight: 代表所有節(jié)點初始權重之和 1+2+5=8
第一次請求:
curWeight 為 [a=0+1,b=0+2,c=0+5] ,選中最大的c做為本次輸出,之后c節(jié)點的權重需要減去sumWeight,調(diào)整后 [a=1,b=2,c=5-8] 也就是 [a=1,b=2,c=-3]
第二次請求:
curWeight 為 [a=1+1,b=2+2,c=-3+5] 結(jié)果為 [a=2,b=4,c=2],選中最大的b作為本次輸出,之后節(jié)點權重變更為 [a=2,b=-4,c=2]
第三次請求:
curWeight 為 [a=2+1,b=-4+2,c=2+5] 結(jié)果為 [a=3,b=-2,c=7],又輪到c(權重大的好處體現(xiàn)出來了),之后節(jié)點權重變更為 [a=3,b=-2,c=-1]
第四次請求:
[a=3,b=-2,c=-1] 加權后[a=4,b=0,c=4],a與c相等,優(yōu)先選前者輸出a
type WeigthRoundRobin struct {
weightAddrs []*weightAddr
}
type weightAddr struct {
addr string// 地址
weight int// 權重
curWeight int// 計算使用
}
func (w *WeigthRoundRobin) Add(param []string) error {
iflen(param) != 2 {
return ErrParam
}
weight, err := strconv.Atoi(param[1])
if err != nil {
return err
}
w.weightAddrs = append(w.weightAddrs, &weightAddr{
addr: param[0],
weight: weight,
curWeight: 0,
})
returnnil
}
func (w *WeigthRoundRobin) Get() (string, error) {
iflen(w.weightAddrs) == 0 {
return"", ErrNoAddr
}
maxWeight := math.MinInt
idx := 0
sumWeight := 0// 權重總和
for k, weightAddr := range w.weightAddrs {
sumWeight += weightAddr.weight // 權重總和
weightAddr.curWeight += weightAddr.weight // 加上權重
if weightAddr.curWeight > maxWeight { // 記錄最大值
maxWeight = weightAddr.curWeight
idx = k
}
}
w.weightAddrs[idx].curWeight -= sumWeight // 減去權重總和
return w.weightAddrs[idx].addr, nil// 返回最大權重的結(jié)果
}有效服務維護方案(參考)
方案一:heart【心跳】
前置配置:
1.啟動docker
docker-compose -f docker-compose-env.yml up -d zookeeper docker-compose -f docker-compose-env.yml up -d kafka
2.修改本地hostsvim /etc/hosts增加 127.0.0.1 kafka

3.kafka常用腳本【可選】 [進入docker中*.sh位于 /opt/kafka/bin目錄]
# 創(chuàng)建topic ./kafka-topics.sh --create --zookeeper zookeeper:2181 --replication-factor 1 --partitions 3 --topic easy_topic # 列出所有topic ./kafka-topics.sh --list --zookeeper zookeeper:2181 # 從頭開始消費 ./kafka-console-consumer.sh --bootstrap-server kafka:9092 --from-beginning --topic easy_topic # 消費組【從最新的消息消費】 ./kafka-console-consumer.sh --bootstrap-server kafka:9092 --consumer-property group.id=testGroup --topic easy_topic # 從最新開始消費 ./kafka-console-consumer.sh --bootstrap-server kafka:9092 --topic easy_topic # 生產(chǎn)消息 ./kafka-console-producer.sh --broker-list kafka:9092 --topic easy_topic
調(diào)度器訂閱kafka消息,同時維護一個有效服務,然后按照負載均衡策略分發(fā)請求。

func main() {
// 服務負責發(fā)送心跳
go heart.RunHeartBeat()
// 調(diào)度器負責接收心跳
go heart.ListenHeartbeat()
// 利用負載均衡獲取
lb := loadbalance.LoadBalanceFactory(loadbalance.BalanceTypeRand)
gofunc() {
for {
time.Sleep(5 * time.Second)
for _, v := range heart.GetAddrList() {
lb.Add([]string{v})
}
fmt.Println(lb.Get())
}
}()
sigusr1 := make(chan os.Signal, 1)
signal.Notify(sigusr1, syscall.SIGTERM)
<-sigusr1
}
方案二:health【健康檢查】
通過HTTP請求服務,維護活躍節(jié)點

func main() {
health.AddAddr("https://www.sina.com.cn/", "https://www.baidu.com/", "http://www.aajklsdfjklsd")
go health.HealthCheck()
time.Sleep(50 * time.Second)
alist := health.GetAliveAddrList()
for i := 0; i < len(alist); i++ {
fmt.Println(alist[i])
}
var block = make(chanbool)
<-block
}
以上就是Golang負載均衡和?;钤O計原理示例探究的詳細內(nèi)容,更多關于Golang負載均衡?;钤O計的資料請關注腳本之家其它相關文章!
相關文章
解讀unsafe.Pointer和uintptr的區(qū)別
這篇文章主要介紹了解讀unsafe.Pointer和uintptr的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02
go語言數(shù)據(jù)結(jié)構之前綴樹Trie
這篇文章主要介紹了go語言數(shù)據(jù)結(jié)構之前綴樹Trie,文章圍繞主題展開詳細內(nèi)容介紹,具有一定得參考價值,需要的小伙伴可以參考一下2022-05-05
golang 監(jiān)聽服務的信號,實現(xiàn)平滑啟動,linux信號說明詳解
這篇文章主要介紹了golang 監(jiān)聽服務的信號,實現(xiàn)平滑啟動,linux信號說明詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-05-05
Golang?WorkerPool線程池并發(fā)模式示例詳解
這篇文章主要為大家介紹了Golang?WorkerPool線程池并發(fā)模式示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08

