负载均衡算法 — 轮询
生活随笔
收集整理的這篇文章主要介紹了
负载均衡算法 — 轮询
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
負載均衡算法 — 輪詢
目錄
1. 概述
| 192.168.10.1:2202 | 1 |
| 192.168.10.2:2202 | 2 |
| 192.168.10.3:2202 | 3 |
| 192.168.10.4:2202 | 4 |
2. 簡單輪詢
1. 算法描述
| 1 | 0 | 192.168.10.1:2202 |
| 2 | 1 | 192.168.10.2:2202 |
| 3 | 2 | 192.168.10.3:2202 |
| 4 | 3 | 192.168.10.4:2202 |
| 5 | 0 | 192.168.10.1:2202 |
2. 代碼實現
type Round struct {curIndex intrss []string }func (r *Round) Add(params ...string) error {if len(params) == 0 {return errors.New("至少需要1個參數")}r.rss = append(r.rss, params...)return nil } func (r *Round) Next() (string, error) {if len(r.rss) == 0 {return "", errors.New("不存在參數")}curElement := r.rss[r.curIndex]r.curIndex = (r.curIndex + 1) % len(r.rss)return curElement, nil }3. 優缺點
2. 加權輪詢
1. 算法描述
假設有 N 臺實例 S = {S1, S2, …, Sn},權重 W = {W1, W2, …, Wn},指示變量 currentPos 表示當前選擇的實例 ID,初始化為 -1;變量 currentWeight 表示當前權重,初始值為 max(S);max(S) 表示 N 臺實例的最大權重值,gcd(S) 表示 N 臺實例權重的最大公約數。
算法可以描述為:
例如,上述 4 個服務,最大權重 max(S) 為 4,最大公約數 gcd(S) 為 1。其調度過程如下:
| 1 | 3 | 4 | 192.168.10.4:2202 |
| 2 | 2 | 3 | 192.168.10.3:2202 |
| 3 | 3 | 3 | 192.168.10.4:2202 |
| 4 | 1 | 2 | 192.168.10.2:2202 |
| … | … | … | …. |
| 9 | 2 | 1 | 192.168.10.3:2202 |
| 10 | 3 | 4 | 192.168.10.4:2202 |
2. 代碼實現
var slaveDns = map[int]map[string]interface{}{0: {"connectstring": "root@tcp(172.16.0.164:3306)/shiqu_tools?charset=utf8", "weight": 2},1: {"connectstring": "root@tcp(172.16.0.165:3306)/shiqu_tools?charset=utf8", "weight": 4},2: {"connectstring": "root@tcp(172.16.0.166:3306)/shiqu_tools?charset=utf8", "weight": 8}, }var last int = -1 //表示上一次選擇的服務器 var cw int = 0 //表示當前調度的權值 var gcd int = 2 //當前所有權重的最大公約數 比如 2,4,8 的最大公約數為:2 var devCount int = 2 //當前機器數func getDns() string {for {last = (last + 1) % len(slaveDns)if last == 0 {cw = cw - gcdif cw <= 0 {cw = getMaxWeight()if cw == 0 {return ""}}}if weight, _ := slaveDns[last]["weight"].(int); weight >= cw {return slaveDns[last]["connectstring"].(string)}} }func getMaxWeight() int {max := 0for _, v := range slaveDns {if weight, _ := v["weight"].(int); weight >= max {max = weight}}return max }func Add(addr string, weight int) {tmap := make(map[string]interface{})tmap["connectstring"] = addrtmap["weight"] = weightslaveDns[devCount] = tmapdevCount = devCount + 1if devCount == 0 {gcd = weight} else {gcd = Gcd(gcd, weight)} }func Gcd(gcd int, weight int) int {for weight != 0 {gcd, weight = weight, gcd%weight}return gcd }3. 優缺點
4. 平滑加權輪詢
1. 算法描述
假設有 N 臺實例 S = {S1, S2, …, Sn},配置權重 W = {W1, W2, …, Wn},有效權重 CW = {CW1, CW2, …, CWn}。每個實例 i 除了存在一個配置權重 Wi 外,還存在一個當前有效權重 CWi,且 CWi 初始化為 Wi;指示變量 currentPos 表示當前選擇的實例 ID,初始化為 -1;所有實例的配置權重和為 weightSum;
那么,調度算法可以描述為:
上述 3 個服務,配置權重和 weightSum 為 7,其調度過程如下:
| 1 | {5, 1, 1} | 0 | 192.168.10.1:2202 | {-2, 1, 1} |
| 2 | {3, 2, 2} | 0 | 192.168.10.1:2202 | {-4, 2, 2} |
| 3 | {1, 3, 3} | 1 | 192.168.10.2:2202 | {1, -4, 3} |
| 4 | {6, -3, 4} | 0 | 192.168.10.1:2202 | {-1, -3, 4} |
| 5 | {4, -2, 5} | 2 | 192.168.10.3:2202 | {4, -2, -2} |
| 6 | {9, -1, -1} | 0 | 192.168.10.1:2202 | {2, -1, -1} |
| 7 | {7, 0, 0} | 0 | 192.168.10.1:2202 | {0, 0, 0} |
| 8 | {5, 1, 1} | 0 | 192.168.10.1:2202 | {-2, 1, 1} |
2. 代碼實現
type LoadBalance interface {//選擇一個后端Server//參數remove是需要排除選擇的后端ServerSelect(remove []string) *Server//更新可用Server列表UpdateServers(servers []*Server) }type Server struct {//主機地址Host string//主機名Name stringWeight int//主機是否在線Online bool }type Weighted struct {Server *ServerWeight intCurrentWeight int //當前機器權重EffectiveWeight int //機器權重 }func (this *Weighted) String() string {return fmt.Sprintf("[%s][%d]", this.Server.Host, this.Weight) }type LoadBalanceWeightedRoundRobin struct {servers []*Serverweighted []*Weighted }func NewLoadBalanceWeightedRoundRobin(servers []*Server) *LoadBalanceWeightedRoundRobin {new := &LoadBalanceWeightedRoundRobin{}new.UpdateServers(servers)return new }func (this *LoadBalanceWeightedRoundRobin) UpdateServers(servers []*Server) {if len(this.servers) == len(servers) {for _, new := range servers {isEqual := falsefor _, old := range this.servers {if new.Host == old.Host && new.Weight == old.Weight && new.Online == old.Online {isEqual = truebreak}}if isEqual == false {goto build}}return}build:log.Println("clients change")log.Println(this.servers)log.Println(servers)weighted := make([]*Weighted, 0)for _, v := range servers {if v.Online == true {w := &Weighted{Server: v,Weight: v.Weight,CurrentWeight: 0,EffectiveWeight: v.Weight,}weighted = append(weighted, w)}}this.weighted = weightedthis.servers = serverslog.Printf("weighted[%v]", this.weighted) }func (this *LoadBalanceWeightedRoundRobin) Select(remove []string) *Server {if len(this.weighted) == 0 {return nil}w := this.nextWeighted(this.weighted, remove)if w == nil {return nil}return w.Server }func (this *LoadBalanceWeightedRoundRobin) nextWeighted(servers []*Weighted, remove []string) (best *Weighted) {total := 0for i := 0; i < len(servers); i++ {w := servers[i]if w == nil {continue}isFind := falsefor _, v := range remove {if v == w.Server.Host {isFind = true}}if isFind == true {continue}w.CurrentWeight += w.EffectiveWeighttotal += w.EffectiveWeightif w.EffectiveWeight < w.Weight {w.EffectiveWeight++}if best == nil || w.CurrentWeight > best.CurrentWeight {best = w}}if best == nil {return nil}best.CurrentWeight -= totalreturn best }func (this *LoadBalanceWeightedRoundRobin) String() string {return "WeightedRoundRobin" }3. 小結
總結
以上是生活随笔為你收集整理的负载均衡算法 — 轮询的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: go interface{}类型转换
- 下一篇: SDL音视频渲染