0 什么是负载均衡?
负载均衡(Load Balance),其含义就是指将负载(工作任务)进行平衡、分摊到多个操作单元上进行运行,从而协同完成工作任务。
负载均衡都分为哪些种类?
软件和硬件负载均衡
- 软件负载均衡
- 硬件负载均衡
本地和全局负载均衡
- 本地负载均衡
- 全局负载均衡
本篇文章的负载均衡算法是属于软件层面的负载均衡。
1 轮询
顾名思义,将子任务在子节点中一个接一个有序的询问请求。
var list = make([]string, 0)
var servers = make(map[string]string)
func init() {
servers = map[string]string{
"stringA": "10.0.0.1",
"stringB": "10.0.0.2",
"stringC": "10.0.0.3",
}
for s := range servers {
list = append(list, s)
}
}
//轮询
var i = 0
func RoundRobin() string {
if i >= len(list) {
i = 0
}
str := servers[list[i]]
i += 1
return str
}
2 随机
在子节点中随机的进行请求。
var list = make([]string, 0)
var servers = make(map[string]string)
func init() {
servers = map[string]string{
"stringA": "10.0.0.1",
"stringB": "10.0.0.2",
"stringC": "10.0.0.3",
}
for s := range servers {
list = append(list, s)
}
}
//随机
func Random() string {
i := rand.Intn(len(list))
return servers[list[i]]
}
3 加权轮询
与轮询不同的是,可以增加权重,就是说权重最大的节点会有更多次数(比例)的请求。
var list = make([]string, 0)
var servers = make(map[string]string)
func init() {
servers = map[string]string{
"stringA": "10.0.0.1",
"stringB": "10.0.0.2",
"stringC": "10.0.0.3",
}
for s := range servers {
list = append(list, s)
}
//加权轮询
var weight_map = map[string]int{
"stringA": 1,
"stringB": 2,
"stringC": 3,
}
for s := range weight_map {
for i := 0; i < weight_map[s]-1; i++ {
list = append(list, s)
}
}
}
//加权轮询
func WeightRoundRobin() string {
if i >= len(list) {
i = 0
}
str := servers[list[i]]
i += 1
return str
}
4 加权随机
与随机不同的是,增加某个节点被随机访问的概率。
var list = make([]string, 0)
var servers = make(map[string]string)
func init() {
servers = map[string]string{
"stringA": "10.0.0.1",
"stringB": "10.0.0.2",
"stringC": "10.0.0.3",
}
for s := range servers {
list = append(list, s)
}
//加权轮询
var weight_map = map[string]int{
"stringA": 1,
"stringB": 2,
"stringC": 3,
}
for s := range weight_map {
for i := 0; i < weight_map[s]-1; i++ {
list = append(list, s)
}
}
}
//加权随机
func WeightRandom() string {
i := rand.Intn(len(list))
return servers[list[i]]
}
5 源地址哈希
该方法是将请求的源地址进行哈希,并将哈希的结果进行取余,将取余后的结果进行节点的匹配最后进行请求。
//Source Hash
func Hash() string {
//对客户端(源)地址做哈希 使用md5哈希算法
has, err := md5.New().Write([]byte("127.0.0.1"))
if err != nil {
panic(err)
}
i := has % len(list)
return servers[list[i]]
}
6 最小连接数
最小连接数法是根据服务器当前的连接情况进行负载均衡的,当请求到来时,会选取当前连接数最少的一台服务器来处理请求。由此也可以延伸出,根据服务器 CPU 占用最少,根据单位时间内处理请求的效率高低等进行服务器选择。最小连接数法只是动态分配服务器的一种算法,通过各种维度的参数计算,可以找到适合不同场景的更均衡的动态分配服务器的方案。
7 全部代码
package main
import (
"crypto/md5"
"math/rand"
"net/http"
)
var list = make([]string, 0)
var servers = make(map[string]string)
func init() {
servers = map[string]string{
"stringA": "10.0.0.1",
"stringB": "10.0.0.2",
"stringC": "10.0.0.3",
}
for s := range servers {
list = append(list, s)
}
//加权轮询
var weight_map = map[string]int{
"stringA": 1,
"stringB": 2,
"stringC": 3,
}
for s := range weight_map {
for i := 0; i < weight_map[s]-1; i++ {
list = append(list, s)
}
}
}
//轮询
var i = 0
func RoundRobin() string {
if i >= len(list) {
i = 0
}
str := servers[list[i]]
i += 1
return str
}
//随机
func Random() string {
i := rand.Intn(len(list))
return servers[list[i]]
}
//Source Hash
func Hash() string {
//对客户端(源)地址做哈希 使用md5哈希算法
has, err := md5.New().Write([]byte("127.0.0.1"))
if err != nil {
panic(err)
}
i := has % len(list)
return servers[list[i]]
}
//加权轮询
func WeightRoundRobin() string {
if i >= len(list) {
i = 0
}
str := servers[list[i]]
i += 1
return str
}
//加权随机
func WeightRandom() string {
i := rand.Intn(len(list))
return servers[list[i]]
}
//----------Web测试---------------//
func main() {
//httpServer(WeightRandom)
}
func httpServer(fun func() string) {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Request Node is " + fun()))
})
http.ListenAndServe(":8888", nil)
}
参考文章: