结合consul和grpc手动实现一个负载均衡算法(随机,轮询)
参考方案:
一、程序结构
---balance
---balance.go
---instance.go
---mgr.go
---random.go
---roudrobin.go
二、代码实现
Balance.go
package balance
type Balancer interface {
DoBalance([]*Instance, ...string) (*Instance, error)
}
Instance.go
package balance
import (
"strconv"
)
type Instance struct {
host string
port int
}
func NewInstance(host string, port int) *Instance {
return &Instance{
host: host,
port: port,
}
}
//定义Instance结构体的方法GetHost()
func (p *Instance) GetHost() string {
return p.host
}
//定义方法GetPort()
func (p *Instance) GetPort() int {
return p.port
}
func (p *Instance) String() string {
return p.host + ":" + strconv.Itoa(p.port)
}
Mgr.go
package balance
import "fmt"
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) {
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
}
random.go
package balance
import (
"errors"
"math/rand"
)
func init() {
RegisterBalancer("random", &RandomBalance{})
}
type RandomBalance struct {
}
func (p *RandomBalance) 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
}
//random.go
Roundronbin.go
package balance
import (
"errors"
)
func init() {
RegisterBalancer("roundrobin", &RoundRobinBalance{})
}
type RoundRobinBalance struct {
curIndex int
}
func (p *RoundRobinBalance) DoBalance(insts []*Instance, key ...string) (inst *Instance, err error) {
if len(insts) == 0 {
err = errors.New("No instance")
return
}
lens := len(insts)
if p.curIndex >= lens {
p.curIndex = 0
}
inst = insts[p.curIndex]
p.curIndex = (p.curIndex + 1) % lens
return
}
//roundrobin.go
https://www.cnblogs.com/pyyu/p/8295590.html
实际方案
创建balance文件夹
Balance.go
package balance
import (
"grpc-go-client/plugins/consul"
"math/rand"
"strconv"
"github.com/hashicorp/consul/api"
)
// var BalanceFun = map[string]interface{}{"round_robin": roundRobin, "random": random}
// 轮询
func RoundRobin(index *int, service, tags string) (string, error) {
target, err := getConsulServices(service, tags)
if err != nil {
return "", err
}
if len(target) <= *index {
*index = 0
}
grpcAddress := target[*index].Service.Address + ":" + strconv.Itoa(target[*index].Service.Port)
*index = (*index + 1) % len(target)
return grpcAddress, nil
}
// 随机
func Random(service, tags string) (string, error) {
target, err := getConsulServices(service, tags)
if err != nil {
return "", err
}
lens := len(target)
index := rand.Intn(lens)
grpcAddress := target[index].Service.Address + ":" + strconv.Itoa(target[index].Service.Port)
return grpcAddress, nil
}
func getConsulServices(service, tags string) ([]*api.ServiceEntry, error) {
consulClient := consul.ConsulClient
target, err := consulClient.GetServices(service, tags)
if err != nil {
return []*api.ServiceEntry{}, err
}
return target, nil
}