Go实现负载均衡
仅仅是对Go语言接口的练习,并无实际业务代码!
balance.go 接口:
1
2
3
4
5
6package balance
type Balance interface {
DoBalance([]*Instance) (*Instance, error)
}instance.go 模拟服务器实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28package balance
import "strconv"
type Instance struct {
host string
port int
}
func NewInstance(host string, port int) *Instance {
return &Instance{
host: host,
port: port,
}
}
func (this *Instance) GetHost() string {
return this.host
}
func (this *Instance) GetPort() int {
return this.port
}
func (this *Instance) String() string {
return this.host + ":" + strconv.Itoa(this.port)
}random.go 模拟负载均衡,随机算法实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27package balance
import (
"errors"
"math/rand"
"time"
)
type RandomBalance struct{}
// init方法 包被引用时调用
func init() {
RegisterBalance("random", &RandomBalance{})
}
func (this *RandomBalance) DoBalance(insts []*Instance) (inst *Instance, err error) {
lens := len(insts)
if lens == 0 {
err = errors.New("Instance is nil")
return
}
rand.Seed(time.Now().Unix())
index := rand.Intn(lens)
inst = insts[index]
return
}roundrobin.go 模拟负载均衡,轮训算法实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32package balance
import (
"errors"
"fmt"
)
// init方法 包被引用时调用
func init() {
RegisterBalance("roundrobin", &RoundRobinBalance{})
}
type RoundRobinBalance struct {
index int
}
func (this *RoundRobinBalance) DoBalance(insts []*Instance) (inst *Instance, err error) {
lens := len(insts)
if lens == 0 {
err = errors.New("Instance is nil")
return
}
if this.index >= lens {
this.index = 0
fmt.Println("一次轮训")
}
inst = insts[this.index]
this.index += 1
return
}mgr.go 对Balance接口实现的管理和注册
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36package balance
import "fmt"
// 声明一个BalanceMgr类型的变量,用来对外暴露注册
var (
mgr = BalanceMgr{
// 这里要注意初始化BalanceMgr结构体的map
allBalancer: make(map[string]Balance),
}
)
type BalanceMgr struct {
allBalancer map[string]Balance
}
// 注册实现Balance接口的结构体
func (this *BalanceMgr) registerBalance(name string, b Balance) {
this.allBalancer[name] = b
}
func RegisterBalance(name string, b Balance) {
mgr.registerBalance(name, b)
}
// 调用对应name的Balance实现类,处理传入的实例slice
func DoBalance(name string, insts []*Instance) (inst *Instance, err error) {
b, ok := mgr.allBalancer[name]
if !ok {
err = fmt.Errorf("Not Fuond %s Balance", name)
}
inst, err = b.DoBalance(insts)
return
}hash.go 模拟负载均衡,一致性hash,对Balance接口的实现 (golang hash值的获取方法)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31package main
import (
"fmt"
"go_dev/day6/example7/balance"
"hash/crc32"
"math/rand"
)
func init() {
balance.RegisterBalance("hash", &HashBalance{})
}
type HashBalance struct{}
func (this *HashBalance) DoBalance(insts []*balance.Instance) (inst *balance.Instance, err error) {
defKey := fmt.Sprintf("%d", rand.Int())
lens := len(insts)
if lens == 0 {
err = fmt.Errorf("not backed instance")
return
}
// 计算hash值
crcTable := crc32.MakeTable(crc32.IEEE)
hashVal := crc32.Checksum([]byte(defKey), crcTable)
// 这里hashVal是uint32的类型 需要转成int进行取余
index := int(hashVal) % lens
inst = insts[index]
return
}main.go 模拟收到请求后,进行请求的分发
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41package main
import (
"fmt"
"go_dev/day6/example7/balance"
"math/rand"
"os"
"time"
)
func main() {
var insts []*balance.Instance
rand.Seed(time.Now().Unix())
// 创建一组机器实例
for i := 0; i < 10; i++ {
host := fmt.Sprintf("192.168.%d.%d", rand.Intn(255), rand.Intn(254)+1)
port := 8888
one := balance.NewInstance(host, port)
insts = append(insts, one)
}
balanceName := "random"
// 从控制台获取输入参数
if len(os.Args) > 1 {
balanceName = os.Args[1]
}
fmt.Printf("use %s balance\n", balanceName)
// 模拟负载均衡
for {
inst, err := balance.DoBalance(balanceName, insts)
if err != nil {
fmt.Printf("do balance err:%s\n", err)
continue
}
fmt.Printf("%v\n", inst)
time.Sleep(time.Second)
}
}文章中并无实际业务代码,仅是对golang接口的练习,和对负载均衡的简单模拟