diff --git a/abstract/IBalance.go b/abstract/IBalance.go index 8e2e5c3..b6e7db8 100644 --- a/abstract/IBalance.go +++ b/abstract/IBalance.go @@ -19,5 +19,5 @@ import ( // Date : 2:44 下午 2021/4/1 type IBalance interface { // Get 获取一个节点 - Get(nodeList []*define.SeverNode) (string, exception.IException) + Get(nodeList []*define.SeverNode) (*define.SeverNode, exception.IException) } diff --git a/abstract/IServer.go b/abstract/IServer.go index 977cf39..7d74546 100644 --- a/abstract/IServer.go +++ b/abstract/IServer.go @@ -14,9 +14,9 @@ import ( // IServer 服务节点集合的接口约束 type IServer interface { - Add(node *define.SeverNode) // 在集群中添加一个节点 - Modify(node *define.SeverNode) // 修改集群中一个节点的信息 - Remove(nodeID string) // 在集群中移除一个节点 - Get() (string, exception.IException) // 获取一个访问节点 - ChangeBalance(d IBalance) // 修改负载均衡策略 + Add(node *define.SeverNode) // 在集群中添加一个节点 + Modify(node *define.SeverNode) // 修改集群中一个节点的信息 + Remove(nodeID string) // 在集群中移除一个节点 + Get() (*define.SeverNode, exception.IException) // 获取一个访问节点 + ChangeBalance(d IBalance) // 修改负载均衡策略 } diff --git a/define/define.go b/define/define.go index e41dacd..1c4b9c0 100644 --- a/define/define.go +++ b/define/define.go @@ -13,12 +13,14 @@ package define // // Date : 2:46 下午 2021/4/1 type SeverNode struct { - ID string `json:"id"` // 机器编号 - Host string `json:"host"` // ip - Port int `json:"port"` // 端口 - Weight float64 `json:"weight"` // 权重 - Status int `json:"status"` // 状态 - Count uint64 `json:"count"` // 节点访问次数, 用于实现最小访问次数的策略 - CostTime uint64 `json:"cost_time"` // 节点访问耗时, 用于实现最小访问耗时的策略 - FailureCount uint64 `json:"failure_count"` // 节点访问失败次数, 用于实现最小访问失败次数的策略 + ID string `json:"id"` // 机器编号 + Host string `json:"host"` // ip + Port int `json:"port"` // 端口 + Weight int64 `json:"weight"` // 权重 + CurrentWeight int64 `json:"current_weight"` // 当前权重 + EffectiveWeight int64 `json:"effective_weight"` // 有效权重 + Status int `json:"status"` // 状态 + Count uint64 `json:"count"` // 节点访问次数, 用于实现最小访问次数的策略 + CostTime uint64 `json:"cost_time"` // 节点访问耗时, 用于实现最小访问耗时的策略 + FailureCount uint64 `json:"failure_count"` // 节点访问失败次数, 用于实现最小访问失败次数的策略 } diff --git a/implement/rand.go b/implement/rand.go index bdb4944..53407d1 100644 --- a/implement/rand.go +++ b/implement/rand.go @@ -1,4 +1,4 @@ -// Package dispatch... +// Package implement ... // // Description : dispatch... // @@ -8,7 +8,6 @@ package implement import ( - "fmt" "git.zhangdeman.cn/gateway/balance/abstract" "git.zhangdeman.cn/zhangdeman/exception" "math/rand" @@ -38,10 +37,10 @@ type Rand struct { // Author : go_developer@163.com<张德满> // // Date : 6:01 下午 2021/4/1 -func (r Rand) Get(nodeList []*define.SeverNode) (string, exception.IException) { +func (r Rand) Get(nodeList []*define.SeverNode) (*define.SeverNode, exception.IException) { if len(nodeList) == 0 { - return "", exception.New(define.ErrorTypeNodeListEmpty, nil, "服务器可用节点为空") + return nil, exception.New(define.ErrorTypeNodeListEmpty, nil, "服务器可用节点为空") } node := nodeList[rand.Intn(len(nodeList))] - return fmt.Sprintf("%s:%d", node.Host, node.Port), nil + return node, nil } diff --git a/implement/round_robin.go b/implement/round_robin.go index e4c3735..fdd8fa7 100644 --- a/implement/round_robin.go +++ b/implement/round_robin.go @@ -8,12 +8,10 @@ package implement import ( - "fmt" "git.zhangdeman.cn/gateway/balance/abstract" "git.zhangdeman.cn/zhangdeman/exception" "git.zhangdeman.cn/gateway/balance/define" - "git.zhangdeman.cn/zhangdeman/easylock" ) // NewRoundRobin 轮询调度 @@ -23,7 +21,6 @@ import ( // Date : 8:07 下午 2021/4/1 func NewRoundRobin() abstract.IBalance { return &RoundRobin{ - lock: easylock.NewLock(), nextNodeIndex: 0, } } @@ -34,7 +31,6 @@ func NewRoundRobin() abstract.IBalance { // // Date : 8:06 下午 2021/4/1 type RoundRobin struct { - lock easylock.EasyLock nextNodeIndex int } @@ -43,19 +39,14 @@ type RoundRobin struct { // Author : go_developer@163.com<张德满> // // Date : 8:05 下午 2021/4/1 -func (r *RoundRobin) Get(nodeList []*define.SeverNode) (string, exception.IException) { +func (r *RoundRobin) Get(nodeList []*define.SeverNode) (*define.SeverNode, exception.IException) { if len(nodeList) == 0 { - return "", exception.New(define.ErrorTypeNodeListEmpty, nil, "服务器可用节点为空") + return nil, exception.New(define.ErrorTypeNodeListEmpty, nil, "服务器可用节点为空") } - _ = r.lock.Lock() - defer func() { - _ = r.lock.Unlock() - }() if r.nextNodeIndex >= len(nodeList) { // 记录过索引之后, 在下次访问之前, 可能移除了某些节点, 所以要检测越界 r.nextNodeIndex = len(nodeList) - 1 } - node := fmt.Sprintf("%s:%d", nodeList[r.nextNodeIndex].Host, nodeList[r.nextNodeIndex].Port) r.nextNodeIndex = (r.nextNodeIndex + 1) % len(nodeList) - return node, nil + return nodeList[r.nextNodeIndex], nil } diff --git a/implement/weight_round_robin.go b/implement/weight_round_robin.go new file mode 100644 index 0000000..63b7b26 --- /dev/null +++ b/implement/weight_round_robin.go @@ -0,0 +1,42 @@ +// Package implement ... +// +// Description : implement ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2025-05-23 23:24 +package implement + +import ( + "git.zhangdeman.cn/gateway/balance/abstract" + "git.zhangdeman.cn/gateway/balance/define" + "git.zhangdeman.cn/zhangdeman/exception" +) + +func NewWeightRoundRobin() abstract.IBalance { + return &WeightRoundRobin{} +} + +// WeightRoundRobin 加权轮询选择机器 +type WeightRoundRobin struct { +} + +func (w *WeightRoundRobin) Get(nodeList []*define.SeverNode) (*define.SeverNode, exception.IException) { + totalWeight := int64(0) + var selectedNode *define.SeverNode + // 计算总权重 + for _, node := range nodeList { + node.CurrentWeight = node.CurrentWeight + node.EffectiveWeight // 每个节点的当前权重 + totalWeight += node.Weight + if nil == selectedNode { + selectedNode = node + } else { + if node.CurrentWeight > selectedNode.CurrentWeight { + selectedNode = node + } + } + } + // 当前选中节点权重重置 + selectedNode.CurrentWeight = selectedNode.CurrentWeight - totalWeight + return selectedNode, nil +} diff --git a/server.go b/server.go index eea2209..36ef20e 100644 --- a/server.go +++ b/server.go @@ -49,6 +49,8 @@ func (s *Server) Add(node *define.SeverNode) { defer func() { s.lock.Unlock() }() + node.EffectiveWeight = node.Weight + node.CurrentWeight = 0 s.NodeList = append(s.NodeList, node) } @@ -75,7 +77,7 @@ func (s *Server) Remove(nodeID string) { // Author : go_developer@163.com<张德满> // // Date : 5:17 下午 2021/4/1 -func (s *Server) Get() (string, exception.IException) { +func (s *Server) Get() (*define.SeverNode, exception.IException) { s.lock.RLock() defer func() { s.lock.RUnlock() @@ -91,6 +93,8 @@ func (s *Server) Modify(node *define.SeverNode) { defer func() { s.lock.RUnlock() }() + node.EffectiveWeight = node.Weight + node.CurrentWeight = 0 findExistNode := false for nodeIndex, item := range s.NodeList { if item.ID == node.ID {