实现一个简单负载均衡调度算法,支持随机、轮训、hash等算法
package balance
import(
"errors"
"math/rand"
)
type Instance struct{
host string
port int
}
func NewInstance(host string, port int) *Instance{
return &Instance{
host:host,
port:port,
}
}
func (p *Instance) GetHost() string{
return p.host
}
func (p *Instance) GetPort() int{
return p.port
}
func (p *Instance) String() string{ //设置打印格式
return p.host + ":" + strconv.Itoa(p.port)
}
type Balancer interface{
DoBalance([]*Instance, ...string)(*Instance,error) //返回一个实例
}
func init(){ //用于BalanceMgr
RegisterBalancer("random", &RandomBalance{})
}
type RandomBalance struct{
}
func (p *RandomBalace) DoBalance(insts []*Instance, key ...string)(inst *Instance,err error){ //实现方法
if len(insts) == 0 {
err = errors.New("No instance")
return
}
lens := len(insts)
index := rand.Intn(lens) //用随机算法实现负载均衡
inst = insts[index]
return
}
func init(){ //用于BalanceMgr
RegisterBalancer("roundrobin", &RoundRobinBalance{})
}
type RoundRobinBalance struct{ //轮询
curIndex int
}
func (p *RoundRobinBalace) DoBalance(insts []*Instance, key ...string)(inst *Instance,err error){ //实现方法
if len(insts) == 0 {
err = errors.New("No instance")
return
}
lens := len(insts)
inst = insts[p,curIndex]
p.curIndex = (p.curIndex + 1) % lens
return
}
package main
import(
"balance" //balance文件位置 注意/不是\
)
func main(){
insts := make([]*balance.Instance) //切片 var insts []*balance.Instance
for i := 0; i < 16; i++{
host := fmt.Sprintln("192.168.%d.%d", rand.Intn(255), rand.Intn(255))
one := balance.NewInstance(host, 8080)
insts = append(insts, one)
}
var balanceName = "random" //默认
if len(os.Args) > 1 {
balanceName = os.Args[1]
}
for{
inst, err := balance.DoBalance(insts)
if err != nil{
fmt.Println("do balance err:", err)
continue
}
fmt.Println(inst)
time.Sleep(time.Second) //调整速度
}
}
//管理所有的负载均衡算法
package balance
type BalanceMgr struct{
allBalancer map[string]Balancer
}
var mgr = BalanceMgr{
allBalancer: make(map[string]Balancer)//初始化
}
func (p *BalanceMgr) registerBalancer(name string, b Balancer){
p.allBalancer[name] = b
}
func RegisterBalancer(name string, b Balancer){
mgr.registerBalancer(name, b)
}
func DoBalance(name string, insts []*Instance)(inst *Instance, err error){ //输入指定balance算法
balancer, ok := mgr.allBalancer[name]
if !ok{
err = fmt.Errorf("Not found %s balancer", name)
return
}
fmt.Printf("use %s balancer\n", name)
inst, err = balancer.DoBalance(insts)
return
}
扩展实现自己的一个利用hash的调度算法,不用改调用方代码
package main
import "balance"
type HashBalance struct{
}
func init(){
balance.RegisterBalance("hash", &HashBalance{})
}
func (p *HashBalance) DoBalance(insts []*balance.Instance, key ...string){
var defKey string = fmt.Sprintf("%d", rand.Int())//默认的key
if len(key) > 0{
defKey =key[0]
}
lens := len(insts) //后端实例个数
if lens == 0{
err = fmt.Println("No backend instance")
return
}
crcTable := crc32.MakeTable(crc32.IEEE)//计算hash
hashVal := crc32.Checksum([]byte(key[0], crcTable))//可变参数
index := int(hashVal) % lens //类似一致性hash,用crc64int越界
inst = insts[index]
return
}