golang實現一個負載均衡(隨機,輪訓)
阿新 • • 發佈:2019-02-14
今天用go實現一個簡單的負載均衡的演算法,雖然簡單,還是要寫一下。
1.首先就是伺服器的資訊,
package balance
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
}
2.接著定義介面
package balance
type Balance interface {
/**
*負載均衡演算法
*/
DoBalance([] *Instance,...string) (*Instance,error)
}
3.接著,是實現介面,random.go
package balance
import (
"errors"
"math/rand"
)
func init() {
RegisterBalance("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
}
roundrobin.go
package balance
import (
"errors"
)
func init() {
RegisterBalance("round", &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++
return
}
4 然後,全部交給管理器來管理,這也是為什麼上面的檔案全部重寫了init函式
package balance
import (
"fmt"
)
type BalanceMgr struct {
allBalance map[string]Balance
}
var mgr = BalanceMgr{
allBalance: make(map[string]Balance),
}
func (p *BalanceMgr) registerBalance(name string, b Balance) {
p.allBalance[name] = b
}
func RegisterBalance(name string, b Balance) {
mgr.registerBalance(name, b)
}
func DoBalance(name string, insts []*Instance) (inst *Instance, err error) {
balance, ok := mgr.allBalance[name]
if !ok {
err = fmt.Errorf("not fount %s", name)
fmt.Println("not found ",name)
return
}
inst, err = balance.DoBalance(insts)
if err != nil {
err = fmt.Errorf(" %s erros", name)
return
}
return
}
下面進行測試:
func main() {
var insts []*balance.Instance
for i := 0; i < 10; i++ {
host := fmt.Sprintf("192.168.%d.%d", rand.Intn(255), rand.Intn(255))
port, _ := strconv.Atoi(fmt.Sprintf("880%d", i))
one := balance.NewInstance(host, port)
insts = append(insts, one)
}
var name = "round"
if len(os.Args) > 1 {
name = os.Args[1]
}
for {
inst, err := balance.DoBalance(name, insts)
if err != nil {
fmt.Println("do balance err")
time.Sleep(time.Second)
continue
}
fmt.Println(inst)
time.Sleep(time.Second)
}
}
5.如果想擴充套件這個,又不入侵原來的程式碼結構,可以類比上面實現dobalance介面即可
package add
import (
"awesomeProject/test/balance"
"fmt"
"math/rand"
"hash/crc32"
)
func init() {
balance.RegisterBalance("hash", &HashBalance{})
}
type HashBalance struct {
key string
}
func (p *HashBalance) DoBalance(insts [] *balance.Instance, key ...string) (inst *balance.Instance, err error) {
defKey := fmt.Sprintf("%d", rand.Int())
if len(key) > 0 {
defKey = key[0]
}
lens := len(insts)
if lens == 0 {
err = fmt.Errorf("no balance")
return
}
hashVal := crc32.Checksum([]byte(defKey), crc32.MakeTable(crc32.IEEE))
index := int(hashVal) % lens
inst = insts[index]
return
}
這樣就能交給管理器統一管理了,而且不會影響原來的api。