分布式系统设计之常见的负载均衡算法

本文涉及的产品
应用型负载均衡 ALB,每月750个小时 15LCU
网络型负载均衡 NLB,每月750个小时 15LCU
传统型负载均衡 CLB,每月750个小时 15LCU
简介: 负载均衡(Load Balance),其含义就是指将负载(工作任务)进行平衡、分摊到多个操作单元上进行运行,从而协同完成工作任务。

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)
}

参考文章:

https://blog.csdn.net/claram/article/details/90290397

相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
6月前
|
负载均衡 运维 监控
负载均衡与容错性:集群模式在分布式系统中的应用
本文由小米分享,解释了分布式系统中的集群模式。集群模式是通过组合多个服务器节点,共同提供服务,实现高可用性、负载均衡和扩展性。文章介绍了主控节点的角色及其高可用性策略,如主备模式和选举机制,并以Zookeeper为例详细阐述了其工作机制。集群模式的优势在于高可用性、负载均衡、扩展性和数据一致性,但也面临节点通信、数据一致性、故障检测和管理等挑战。最后,作者鼓励读者讨论和交流相关技术问题。
292 5
|
7月前
|
负载均衡 应用服务中间件 nginx
服务器架构、分布式系统、负载均衡、微服务、高可用性
**分布式系统取代单体架构,以微服务实现高扩展性和灵活性。通过负载均衡技术增强性能,防止单点故障,结合冗余备份与故障切换保障高可用性,这种架构是支撑大规模在线业务的关键。**
162 3
|
7月前
|
负载均衡 算法
软件体系结构 - 负载均衡算法
软件体系结构 - 负载均衡算法
56 4
|
7月前
|
存储 缓存 运维
解密一致性哈希算法:实现高可用和负载均衡的秘诀
解密一致性哈希算法:实现高可用和负载均衡的秘诀
928 0
|
负载均衡 网络协议 Dubbo
高并发系统设计之负载均衡
通过负载均衡,我们能提高系统的可用性,提升响应速度,同时也能防止任何单一的资源过度使用。
352 0
|
缓存 分布式计算 负载均衡
面试:第九章:分布式 、高并发、集群、负载均衡、高可用(上)
面试:第九章:分布式 、高并发、集群、负载均衡、高可用
448 0
面试:第九章:分布式 、高并发、集群、负载均衡、高可用(上)
|
负载均衡 算法
分布式系统设计之常见的负载均衡算法
分布式系统设计之常见的负载均衡算法
|
域名解析 缓存 负载均衡
面试:第九章:分布式 、高并发、集群、负载均衡、高可用(下)
面试:第九章:分布式 、高并发、集群、负载均衡、高可用
219 0
|
负载均衡 算法 Dubbo
第02篇:分布式负载均衡
什么叫`负载均衡`, 所谓负载。先可以理解为当流量请求到某一个微服务应用, 则这么微服务应用就承受了负载。 `什么叫均衡`如下图,浏览器发送了3次请求,后台有2个节点的微服务应用。但是每次都请求在某一台。而另外一台一直空闲没有流量。这种情况就是不均衡的。
145 0
|
负载均衡 算法
彻底揭秘负载均衡算法与实现!深入剖析负载均衡核心(下)
彻底揭秘负载均衡算法与实现!深入剖析负载均衡核心
179 0
彻底揭秘负载均衡算法与实现!深入剖析负载均衡核心(下)