16 Commits

13 changed files with 570 additions and 76 deletions

30
balance/abstract.go Normal file
View File

@ -0,0 +1,30 @@
// Package balance...
//
// Description : balance...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-11-22 4:45 下午
package balance
import (
"net/http"
"git.zhangdeman.cn/zhangdeman/gopkg/balance/define"
)
// IBalance 负载算法接口约束
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 4:45 下午 2021/11/22
type IBalance interface {
// GetServerNode 获取一个服务器节点
GetServerNode(req *http.Request) (*define.ServerNode, error)
// AddServerNode 新增一个服务器节点
AddServerNode(node *define.ServerNode) error
// Remove 移除一个节点
Remove(hostIP string, port int, force bool)
// GetServerNodeList 获取服务节点列表
GetServerNodeList() []*define.ServerNode
}

View File

@ -7,7 +7,12 @@
// Date : 2021-10-19 2:26 下午 // Date : 2021-10-19 2:26 下午
package balance package balance
import "sync" import (
"errors"
"sync"
"git.zhangdeman.cn/zhangdeman/gopkg/balance/define"
)
// base ... // base ...
// //
@ -15,7 +20,8 @@ import "sync"
// //
// Date : 2:26 下午 2021/10/19 // Date : 2:26 下午 2021/10/19
type base struct { type base struct {
lock *sync.RWMutex lock *sync.RWMutex
severList []*define.ServerNode
} }
// Lock ... // Lock ...
@ -53,3 +59,53 @@ func (b *base) RLock() {
func (b *base) RUnlock() { func (b *base) RUnlock() {
b.lock.RUnlock() b.lock.RUnlock()
} }
// AddServerNode 新添加一个服务器节点
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:07 下午 2021/10/20
func (b *base) AddServerNode(node *define.ServerNode) error {
if len(node.HostIP) == 0 || node.Port <= 0 {
return errors.New("host ip or port is invalid")
}
b.Lock()
defer b.Unlock()
for _, item := range b.severList {
if item.HostIP == node.HostIP && item.Port == node.Port {
return errors.New("host config is already exist")
}
}
b.severList = append(b.severList, node)
return nil
}
// Remove 移除一个节点, force = true , 强制删除, force = false 逻辑删除, 设置状态
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:19 下午 2021/10/20
func (b *base) Remove(hostIP string, port int, force bool) {
b.Lock()
defer b.Unlock()
tmpServerNode := make([]*define.ServerNode, 0)
for _, item := range b.severList {
if item.HostIP == hostIP && item.Port == port {
if force {
continue
}
item.Status = define.ServerNodeStatusRemove
}
tmpServerNode = append(tmpServerNode, item)
}
b.severList = tmpServerNode
}
// GetServerNodeList 获取服务器节点
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:33 下午 2021/10/20
func (b *base) GetServerNodeList() []*define.ServerNode {
return b.severList
}

View File

@ -13,8 +13,9 @@ package define
// //
// Date : 12:36 下午 2021/10/19 // Date : 12:36 下午 2021/10/19
type ServerNode struct { type ServerNode struct {
HostIP string `json:"host_ip"` // 机器IP HostIP string `json:"host_ip"` // 机器IP
Port int `json:"port"` // 机器端口 Port int `json:"port"` // 机器端口
Status int `json:"status"` // 机器状态 Status int `json:"status"` // 机器状态
Weight int `json:"weight"` // 机器权重 Weight float64 `json:"weight"` // 机器权重
CurrentWeight float64 `json:"current_weight"` // 当前权重
} }

62
balance/ip_hash.go Normal file
View File

@ -0,0 +1,62 @@
// Package balance...
//
// Description : balance...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-11-22 4:39 下午
package balance
import (
"net/http"
"sync"
"git.zhangdeman.cn/zhangdeman/gopkg/util"
"github.com/pkg/errors"
"git.zhangdeman.cn/zhangdeman/gopkg/balance/define"
)
// NewIPHash ip hash 负载均衡
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 4:53 下午 2021/11/22
func NewIPHash(severList []*define.ServerNode) (IBalance, error) {
if nil == severList || len(severList) == 0 {
return nil, errors.New("sever list is empty")
}
return &IPHash{
base: base{
lock: &sync.RWMutex{},
severList: severList,
},
serverList: severList,
}, nil
}
// IPHash ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 4:57 下午 2021/11/22
type IPHash struct {
base
serverList []*define.ServerNode
}
// GetServerNode ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 4:53 下午 2021/11/22
func (ih *IPHash) GetServerNode(req *http.Request) (*define.ServerNode, error) {
clintIPHashID := util.GetHashID(util.GetRemoteIp(req))
ih.RLock()
defer ih.RUnlock()
if len(ih.serverList) == 0 {
return nil, errors.New("sever list is empty")
}
return ih.serverList[int(clintIPHashID%uint64(len(ih.serverList)))], nil
}

View File

@ -8,6 +8,7 @@
package balance package balance
import ( import (
"net/http"
"sync" "sync"
"git.zhangdeman.cn/zhangdeman/gopkg/balance/define" "git.zhangdeman.cn/zhangdeman/gopkg/balance/define"
@ -19,15 +20,15 @@ import (
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 12:40 下午 2021/10/19 // Date : 12:40 下午 2021/10/19
func NewPoll(serverList []*define.ServerNode) (*Poll, error) { func NewPoll(serverList []*define.ServerNode) (IBalance, error) {
if nil == serverList || len(serverList) == 0 { if nil == serverList || len(serverList) == 0 {
return nil, errors.New("server list is empty") return nil, errors.New("server list is empty")
} }
return &Poll{ return &Poll{
base: base{ base: base{
lock: &sync.RWMutex{}, lock: &sync.RWMutex{},
severList: serverList,
}, },
serverList: serverList,
currentServerIndex: 0, currentServerIndex: 0,
}, nil }, nil
} }
@ -39,7 +40,6 @@ func NewPoll(serverList []*define.ServerNode) (*Poll, error) {
// Date : 12:41 下午 2021/10/19 // Date : 12:41 下午 2021/10/19
type Poll struct { type Poll struct {
base base
serverList []*define.ServerNode
currentServerIndex int currentServerIndex int
} }
@ -48,21 +48,18 @@ type Poll struct {
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 12:43 下午 2021/10/19 // Date : 12:43 下午 2021/10/19
func (p *Poll) GetServerNode() (*define.ServerNode, error) { func (p *Poll) GetServerNode(req *http.Request) (*define.ServerNode, error) {
if len(p.serverList) == 0 { p.RLock()
return nil, errors.New("server list is empty") defer p.RUnlock()
}
p.Lock()
defer p.Unlock()
var ( var (
serverNode *define.ServerNode serverNode *define.ServerNode
) )
// 循环次数 // 循环次数
loopTimes := 0 loopTimes := 0
for loopTimes < len(p.serverList) { for loopTimes < len(p.severList) {
loopTimes++ loopTimes++
p.currentServerIndex = (p.currentServerIndex + 1) % len(p.serverList) p.currentServerIndex = (p.currentServerIndex + 1) % len(p.severList)
if serverNode = p.serverList[p.currentServerIndex]; serverNode.Status != define.ServerNodeStatusNormal { if serverNode = p.severList[p.currentServerIndex]; serverNode.Status != define.ServerNodeStatusNormal {
continue continue
} }
break break
@ -74,57 +71,3 @@ func (p *Poll) GetServerNode() (*define.ServerNode, error) {
return serverNode, nil return serverNode, nil
} }
// AddServerNode 新添加一个服务器节点
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:07 下午 2021/10/20
func (p *Poll) AddServerNode(hostIP string, port int) error {
if len(hostIP) == 0 || port <= 0 {
return errors.New("host ip or port is invalid")
}
p.Lock()
defer p.Unlock()
for _, item := range p.serverList {
if item.HostIP == hostIP && item.Port == port {
return errors.New("host config is already exist")
}
}
p.serverList = append(p.serverList, &define.ServerNode{
HostIP: hostIP,
Port: port,
Status: define.ServerNodeStatusNormal,
})
return nil
}
// Remove 移除一个节点, force = true , 强制删除, force = false 逻辑删除, 设置状态
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:19 下午 2021/10/20
func (p *Poll) Remove(hostIP string, port int, force bool) {
p.Lock()
defer p.Unlock()
tmpServerNode := make([]*define.ServerNode, 0)
for _, item := range p.serverList {
if item.HostIP == hostIP && item.Port == port {
if force {
continue
}
item.Status = define.ServerNodeStatusRemove
}
tmpServerNode = append(tmpServerNode, item)
}
p.serverList = tmpServerNode
}
// GetServerNodeList 获取服务器节点
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:33 下午 2021/10/20
func (p *Poll) GetServerNodeList() []*define.ServerNode {
return p.serverList
}

59
balance/random.go Normal file
View File

@ -0,0 +1,59 @@
// Package balance...
//
// Description : balance...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-11-22 6:27 下午
package balance
import (
"errors"
"net/http"
"sync"
"git.zhangdeman.cn/zhangdeman/gopkg/util"
"git.zhangdeman.cn/zhangdeman/gopkg/balance/define"
)
// NewRandom ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 6:29 下午 2021/11/22
func NewRandom(severList []*define.ServerNode) (IBalance, error) {
if nil == severList || len(severList) == 0 {
return nil, errors.New("sever list is empty")
}
return &Random{
base{
lock: &sync.RWMutex{},
severList: make([]*define.ServerNode, 0),
},
}, nil
}
// Random 随机负载均衡
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 6:27 下午 2021/11/22
type Random struct {
base
}
// GetServerNode ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 6:31 下午 2021/11/22
func (r *Random) GetServerNode(req *http.Request) (*define.ServerNode, error) {
r.RLock()
defer r.RUnlock()
if len(r.severList) == 0 {
return nil, errors.New("sever list is empty")
}
randomID := util.GetHashID(util.GenRandomString("", 128)) % uint64(len(r.severList))
return r.severList[int(randomID)], nil
}

View File

@ -0,0 +1,114 @@
// Package balance...
//
// Description : balance...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-11-22 6:58 下午
package balance
import (
"net/http"
"sync"
"github.com/pkg/errors"
"git.zhangdeman.cn/zhangdeman/gopkg/balance/define"
)
// NewWeightServerRoundRobin ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 6:58 下午 2021/11/22
func NewWeightServerRoundRobin(severList []*define.ServerNode) (IBalance, error) {
if nil == severList || len(severList) == 0 {
return nil, errors.New("sever list is empty")
}
return &WeightServerRoundRobin{
base: base{
lock: &sync.RWMutex{},
severList: severList,
},
effectiveWeight: 0,
}, nil
}
// WeightServerRoundRobin 加权轮询
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 6:58 下午 2021/11/22
type WeightServerRoundRobin struct {
base
effectiveWeight float64
}
// GetServerNode ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 7:00 下午 2021/11/22
func (w *WeightServerRoundRobin) GetServerNode(req *http.Request) (*define.ServerNode, error) {
w.RLock()
defer w.RUnlock()
if len(w.severList) == 0 {
return nil, errors.New("sever list is empty")
}
var expectBackendServer *define.ServerNode
for _, backendServer := range w.severList {
// 给每个后端服务增加自身权重
backendServer.CurrentWeight += backendServer.Weight
if expectBackendServer == nil {
expectBackendServer = backendServer
}
if backendServer.CurrentWeight > expectBackendServer.CurrentWeight {
expectBackendServer = backendServer
}
}
// 把选择的后端服务权重减掉总权重
expectBackendServer.CurrentWeight -= w.effectiveWeight
return expectBackendServer, nil
}
// AddServerNode 新添加一个服务器节点
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:07 下午 2021/10/20
func (w *WeightServerRoundRobin) AddServerNode(node *define.ServerNode) error {
if len(node.HostIP) == 0 || node.Port <= 0 {
return errors.New("host ip or port is invalid")
}
w.Lock()
defer w.Unlock()
for _, item := range w.severList {
if item.HostIP == node.HostIP && item.Port == node.Port {
return errors.New("host config is already exist")
}
}
w.effectiveWeight += node.Weight
w.severList = append(w.severList, node)
return nil
}
// Remove 移除一个节点, force = true , 强制删除, force = false 逻辑删除, 设置状态
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:19 下午 2021/10/20
func (w *WeightServerRoundRobin) Remove(hostIP string, port int, force bool) {
w.Lock()
defer w.Unlock()
tmpServerNode := make([]*define.ServerNode, 0)
for _, item := range w.severList {
if item.HostIP == hostIP && item.Port == port {
if force {
continue
}
item.Status = define.ServerNodeStatusRemove
}
tmpServerNode = append(tmpServerNode, item)
}
w.severList = tmpServerNode
}

View File

@ -0,0 +1,103 @@
// Package consistent_hash...
//
// Description : consistent_hash...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-11-21 4:57 下午
package consistent_hash
import (
"sort"
"strconv"
"sync"
)
// New 获取实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 5:03 下午 2021/11/21
func New(replicas int, fn HashFunc) *Consistent {
if nil == fn {
fn = DefaultHashFunc
}
return &Consistent{
hashFunc: fn,
replicas: replicas,
keys: make([]int, 0),
hashMap: make(map[int]string),
lock: &sync.RWMutex{},
}
}
// Consistent ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 5:00 下午 2021/11/21
type Consistent struct {
hashFunc HashFunc // 哈希函数
replicas int // 虚拟的数量
keys []int // 哈希环
hashMap map[int]string // 虚拟节点与真实节点的映射表
lock *sync.RWMutex // 锁
}
// Add 添加节点
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 5:10 下午 2021/11/21
func (c *Consistent) Add(keyList ...string) {
c.lock.Lock()
defer c.lock.Unlock()
for _, key := range keyList {
for i := 0; i < c.replicas; i++ {
hash := int(c.hashFunc([]byte(strconv.Itoa(i) + key)))
c.keys = append(c.keys, hash)
c.hashMap[hash] = key
}
}
// 哈希值排序
sort.Ints(c.keys)
}
// Get 获取节点
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 5:16 下午 2021/11/21
func (c *Consistent) Get(key string) string {
c.lock.RLock()
defer c.lock.Unlock()
if len(c.keys) == 0 {
return ""
}
hash := int(c.hashFunc([]byte(key)))
// 查找节点索引
idx := sort.Search(len(c.keys), func(i int) bool {
return c.keys[i] >= hash
})
return c.hashMap[c.keys[idx%len(c.keys)]]
}
// Delete 删除一个节点,本质逻辑 : 重建哈希环
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 5:35 下午 2021/11/21
func (c *Consistent) Delete(key string) {
c.lock.Lock()
defer c.lock.Unlock()
tmpKeyList := make([]string, 0)
for _, k := range c.hashMap {
if k == key {
continue
}
tmpKeyList = append(tmpKeyList, k)
}
c.hashMap = make(map[int]string)
c.keys = make([]int, 0)
c.Add(tmpKeyList...)
}

22
consistent_hash/define.go Normal file
View File

@ -0,0 +1,22 @@
// Package consistent_hash...
//
// Description : consistent_hash...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-11-21 4:49 下午
package consistent_hash
import "hash/crc32"
// HashFunc 哈希函数定义
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 4:50 下午 2021/11/21
type HashFunc func(data []byte) uint32
var (
// DefaultHashFunc 默认的哈希函数
DefaultHashFunc = crc32.ChecksumIEEE
)

View File

@ -100,3 +100,75 @@ func (r *Read) GetAllDataToMap(fieldList []string) (map[string][]map[string]stri
// 格式化数据 // 格式化数据
return formatResult, nil return formatResult, nil
} }
// ExtractAssignCol 抽取指定的列并返回list数据, 列的计数从 0 开始
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 4:53 下午 2021/11/19
func (r *Read) ExtractAssignCol(colIndexList []int) (map[string][][]string, error) {
var (
allData map[string][][]string
err error
formatResult map[string][][]string
)
if allData, err = r.GetAllData(); nil != err {
return nil, err
}
formatResult = make(map[string][][]string)
for sheetName, sheetData := range allData {
formatResult[sheetName] = make([][]string, 0)
for _, lineData := range sheetData {
tmpData := make([]string, 0)
for _, colIdx := range colIndexList {
if len(lineData) <= colIdx {
// 索引越界,默认空值
tmpData = append(tmpData, "")
continue
}
tmpData = append(tmpData, lineData[colIdx])
}
formatResult[sheetName] = append(formatResult[sheetName], tmpData)
}
}
return formatResult, nil
}
// ExtractAssignColToMap 抽取指定的列并返回map数据
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 4:53 下午 2021/11/19
func (r *Read) ExtractAssignColToMap(ruleTable map[int]string) (map[string][]map[string]string, error) {
var (
allData map[string][][]string
err error
formatResult map[string][]map[string]string
)
formatResult = make(map[string][]map[string]string)
if allData, err = r.GetAllData(); nil != err {
return nil, err
}
for sheetName, sheetData := range allData {
formatResult[sheetName] = make([]map[string]string, 0)
for _, lineData := range sheetData {
tmpResult := make(map[string]string)
for idx, colData := range lineData {
colName, exist := ruleTable[idx]
if !exist {
// 当前字段不需要提取
continue
}
tmpResult[colName] = colData
}
for _, colName := range ruleTable {
if _, exist := tmpResult[colName]; !exist {
tmpResult[colName] = ""
}
}
formatResult[sheetName] = append(formatResult[sheetName], tmpResult)
}
}
// 格式化数据
return formatResult, nil
}

View File

@ -1,4 +1,4 @@
// Package gin ... // Package api ...
// //
// Description : 便捷的相关API处理 // Description : 便捷的相关API处理
// //
@ -23,7 +23,7 @@ type IApi interface {
GetURI() string GetURI() string
// GetMiddleWareList 使用的中间件列表 // GetMiddleWareList 使用的中间件列表
GetMiddleWareList() []gin.HandlerFunc GetMiddleWareList() []gin.HandlerFunc
// 处理的handler // GetHandler 处理的handler
GetHandler() gin.HandlerFunc GetHandler() gin.HandlerFunc
} }

View File

@ -0,0 +1,8 @@
// Package tile38 ...
//
// Description : tile38 ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-11-18 3:45 下午
package tile38

View File

@ -7,7 +7,10 @@
// Date : 2021-03-09 5:56 下午 // Date : 2021-03-09 5:56 下午
package util package util
import "net" import (
"net"
"net/http"
)
// GetHostIP 获取本机IP地址 // GetHostIP 获取本机IP地址
// //
@ -27,3 +30,24 @@ func GetHostIP() string {
} }
return hostIP return hostIP
} }
// GetRemoteIp 获取远端IP
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 5:35 下午 2021/11/22
func GetRemoteIp(req *http.Request) string {
// Try via request
ip, _, err := net.SplitHostPort(req.RemoteAddr)
if err != nil {
return "::1"
}
userIP := net.ParseIP(ip)
if userIP == nil {
return "::1"
}
return userIP.String()
}