引言
你说妹子太多了,压力有点大,身体有点吃不消,有点支持不住了。
于是乎,你找了几个兄弟说:哥们,帮忙分担一下压力呗。于是你开始把这些妹子推向你兄弟的魔爪,把妹子一个个的介绍给你不同的兄弟,并且尽力撮合他们。PS: 当然自己得留点。
这大概就是负载均衡,你既充当着负载均衡器, 也充当着服务器, 你的兄弟就是个服务器。你的压力相比之下减少了很多,这就是负载均衡的作用。
用专业术语来说:
- 负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。
- 负载均衡(Load Balance)其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。
简单点来说:
- 其实就是请求太多,一台服务器处理不过来,把它分摊到多台服务器处理。
那么如何将请求分摊到多台服务器?
接下来一一介绍常见的几种负载均衡算法。
轮询法
- 将请求按顺序轮流地分配到后端服务器上,它均衡地对待后端的每一台服务器,而不关心服务器实际的连接数和当前的系统负载。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eAolzy2P-1619539822631)(https://www.classmatelin.top/images/20210427234214.png)]
-
Go语言实现示例如下:
/** * Author: ClassmateLin * Site: https://www.classmatelin.top * mail: classmatelin.site@gmail.com * Date: 2021/4/26 21:32 */
package main
import (
"fmt"
)
type RoundRobin struct {
servers []string
current int
}
/** 获取下一个服务器 */
func (R *RoundRobin) next() string {
R.current++
R.current = R.current % len(R.servers) // 访问到最后一个服务器之后,重置会第一台。 5%5=0。
return R.servers[R.current]
}
func main() {
r := &RoundRobin{
servers: []string{
"192.168.10", "192.168.11", "192.168.12"},
current: -1,
}
for i := 0; i < 10; i++ {
fmt.Printf("| %d | %s |\n", i + 1, r.next())
}
}
加权轮询法
-
每台后端服务器的配置可能不太一样,有些性能好,能处理的请求多, 有些则性能比较差,能处理的请求较少。
-
它们的抗压能力不相同,因此按顺序的分配服务器的话导致性能好的服务器无法发挥最大作用,性能差的服务器压力太大。
-
那么加权轮询法可以解决这个问题,给性能好的服务器分配较高的权重,性能差的服务器分配较低的权重。
-
go语言实现的平滑的加权轮询法:
/** * @Author: ClassmateLin * @Site: https://www.classmatelin.top * @Email: classmatelin.site@gmail.com * @Date: 2021/4/27 22:44 */
package main
import "fmt"
type Server struct {
host string // 主机地址
weight int // 配置的权重
currentWeight int // 当前权重
}
func getSever(servers []*Server) (s *Server) {
allWeight := 0 // 总权重
for _, server := range servers {
if server == nil {
return nil
}
// 每一轮选择都用自身的权重加到当前权重
allWeight += server.weight
server.currentWeight += server.weight
// 当前未选中节点或当前节点比之前选中的节点权重高,那么更新当前选中的节点
if s == nil || server.currentWeight > s.currentWeight{
s = server
}
}
s.currentWeight -= allWeight
return
}
func main() {
servers := []*Server{
{
"192.168.10.10", 5, 0},
{
"192.168.10.11", 2, 0},
{
"192.168.10.12", 1, 0},
}
for i := 0; i < 20; i++ {
server := getSever(servers)
if server == nil {
continue
}
fmt.Printf("| %s | %d |\n", server.host, server.weight)
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eVhLqR1j-1619539822633)(https://www.classmatelin.top/images/20210427233715.png)]
A: {
host:"192.168.10.10", "weight": 3}
B: {
host:"192.168.10.11", "weight": 1}
C: {
host:"192.168.10.12", "weight": 1}
如果出现的序列为AAABC, 可能会给第一台机器造成压力过大。如果出现的序列为ABACA,避免同时造成同一台服务器压力过大的问题,就是平滑的。)
随机法
/** * @Author: ClassmateLin * @Site: https://www.classmatelin.top * @Email: classmatelin.site@gmail.com * @Date: 2021/4/27 22:44 */
package main
import (
"fmt"
"math/rand"
)
type Random struct {
servers []string
}
func (R *Random) next() string {
return R.servers[rand.Intn(len(R.servers))]
}
func main() {
r := Random{
servers: []string{
"192.168.10.10", "192.168.10.11", "192.168.10.12"},
}
for i := 0; i < 10; i++ {
fmt.Println(r.next())
}
}
加权随机法
源地址哈希法
最小数连接法