负载均衡的原理及算法

在这里插入图片描述

一、定义

负载均衡(Load Balancing)是一种计算机网络和服务器管理技术,旨在分配网络流量、请求或工作负载到多个服务器或资源,以确保这些服务器能够高效、均匀地处理负载,并且能够提供更高的性能、可用性和可扩展性。

二、负载均衡算法

1.Round Robin-轮询

轮询,顾名思义,把请求按顺序分配给每个服务器,然后重复执行这个顺序,进行请求分配。如下图:

在这里插入图片描述

如上图,有3台服务器,分别为服务器A、服务器B和服务器C,当客户端有请求过来时,请求会按照 A->B->C->A->B->C->… 这种轮询的顺序分配给各个服务器。

(1) 原理:

  • 服务器列表:维护一个服务器列表,有服务器加入/剔除时,相应的更新服务器列表;
  • 服务器游标:记录需要处理下一个请求的服务器;
  • 请求分发:新请求到达,选择当前服务器来处理该请求,然后服务器游标+1;
  • 循环:不断重复步骤3,以确保每个服务器都有机会处理请求;

(2) 算法实现

方法1:

轮询算法的实现非常简单,可以定义一个服务器的列表和当前服务器指针,如下伪代码:

# 服务器列表
servers = ["ServerA", "ServerB", "ServerC"]
# 当前服务器
current_server = 0
# 轮询算法
if(req):# 选择当前服务器来处理请求process_request(servers[current_server])# 将当前服务器移到服务器列表的末尾if current_server == length(servers):current_server = 0else:# 指针+1current_server += 1

当客户端有新的请求到达时,负载均衡器会选择服务器指针(current_server)指向的服务器来处理请求,然后将当前服务器指针移到下一个服务器(current_server += 1), 如果 current_server=服务器总数,则把current_server设置为0,进行下一场轮询。

方法2: 循环列表

循环列表是一个环形数据结构,用于按照顺序循环遍历服务器列表。当指针指向列表的末尾时,指针会回到列表的开头,从而实现循环。如下伪代码:

servers = ["Server1", "Server2", "Server3"]  # 服务器列表
current_index = 0  # 当前服务器的索引def get_next_server(self):if not self.servers:return None# 获取当前服务器current_server = self.servers[self.current_index]# 更新索引,移到下一个服务器self.current_index = (self.current_index + 1) % len(self.servers)return current_server# 创建一个包含服务器的列表
servers_list = ["ServerA", "ServerB", "ServerC"]# 模拟请求的处理过程
if(req):  # 假设有5个请next_server = get_next_server()if next_server is not None:process_request(next_server)else:print("No available servers.")

(3) 优缺点

优点:简单,实现成本低;

缺点:

  • 无法根据服务器的负载情况来分配请求,当服务器的负载不均衡时,轮询算法无法自动调整。
  • 当服务器down机了,轮询算法无法自动剔除该服务器,导致请求会被转发到down机的服务器上。
servers = ["Server1", "Server2", "Server3"]  # 服务器列表
current_index = 0  # 当前服务器的索引def get_next_server(self):if not self.servers:return None# 获取当前服务器current_server = self.servers[self.current_index]# 更新索引,移到下一个服务器self.current_index = (self.current_index + 1) % len(self.servers)return current_server# 创建一个包含服务器的列表
servers_list = ["ServerA", "ServerB", "ServerC"]# 模拟请求的处理过程
if(req):  # 假设有5个请next_server = get_next_server()if next_server is not None:process_request(next_server)else:print("No available servers.")

(4) 适用场景

对服务器没有什么特别的要求,就可以采用轮询算法,比如:Nginx 默认适用的就是轮询算法。

2.Weighted Round Robin - 加权轮询

加权轮询算法是轮询算法的一种改进,只不过在负载时会根据服务器的权重来分配请求,权重越大,分配的请求就会越多。如下图:
在这里插入图片描述

(1) 算法实现

实现算法和轮询很类似,只不过会根据权重在列表中放置不同比例的服务器,同时定义一个服务器的列表和当前服务器指针,如下伪代码:

# 服务器列表
servers = ["ServerA", "ServerA", "ServerA", "ServerB","ServerB", "ServerC"]
# 当前服务器
current_server = 0
# 轮询算法
if(req):# 选择当前服务器来处理请求process_request(servers[current_server])# 将当前服务器移到服务器列表的末尾if current_server == length(servers):current_server = 0else:# 指针+1current_server += 1

当客户端有新的请求到达时,负载均衡器会选择服务器指针(current_server)指向的服务器来处理请求,然后将当前服务器指针移到下一个服务器(current_server += 1), 如果 current_server=服务器总数,则把current_server设置为0,进行下一场轮询。

(2) 优缺点

优点:可以人为配置权重,为处理能力强的服务器配置高的权重,处理能力弱的配置低的权重,从而实现负载均衡。

缺点:无法应对服务器动态变化的情况,比如:服务器down机了,无法自动剔除该服务器,导致请求会被转发到down机的服务器上。

(3) 适用场景

服务器的处理能力不一致,可以采用加权轮询算法。

比如:有3台服务器,服务器A(4C8G,4个CPU,8G内存),服务器B(2C4G,2个CPU,4G内存),服务器C(1C2G,1个CPU,2G内存),那么可以配置服务器A的权重为4,服务器B的权重为2,服务器C的权重为1。

3.Least Connections - 最小连接数

最小连接数,是指把请求分配给当前连接数最少的服务器,以确保负载更均匀。如下图:

在这里插入图片描述

上图中有 3台服务器,服务器A(连接数10)、服务器B(连接数100)和服务器C(连接数1000),连接数最少的服务器A分配的Req比其他服务器多。

(1) 原理

  • 维护一个所有服务器和连接数的字典(Map);
  • 当新的请求到达时,负载均衡器会检查服务器列表中当前连接数最少的服务器;
  • 请求将被分配给具有最少连接数的服务器,处理请求后该服务器的连接数+1;
  • 如果有多台服务器具有相同的最小连接数,算法可以使用其他标准来选择其中一台,如加权等。

(2) 算法实现

如下伪代码:

# 创建一个包含服务器及其连接数的字典
servers = {"Server A": 5, "Server B": 3, "Server C": 4}def get_server_with_least_connections():# 找到当前连接数最少的服务器min_connections = min(servers.values())# 找到具有最小连接数的服务器for server, connections in servers.items():if connections == min_connections:return server# 选择连接数最少的服务器
def assign_request(self):# 获取具有最小连接数的服务器server = get_server_with_least_connections()if server is not None:# 模拟分配请求给服务器,增加连接数self.servers[server] += 1return serverelse:return "No available servers."# 模拟请求的处理过程
if req:  # 假设有请求assigned_server = load_balancer.assign_request()

(3) 优缺点

优点:

  • 动态负载均衡:它根据服务器的当前负载情况来做出决策,这使得它能够有效地分配请求给当前连接数最少的服务器,从而确保了服务器资源的最佳利用。
  • 适应性强:这个算法适用于服务器性能不均匀的情况,因为它关注的是连接数,而不是服务器的硬件配置或性能评估。
  • 避免过载:通过将新请求分配给连接数最少的服务器,”最小连接数”算法有助于防止某些服务器被过度加载,从而提高了系统的稳定性和性能。
  • 自动恢复:如果某台服务器由于故障或重启而导致连接数清零,该算法会自动开始将新请求分配给该服务器,以实现自动恢复。

缺点:

  • 连接数不一定代表负载:”最小连接数”算法假设连接数与服务器的负载成正比,但这并不总是准确。有时候,某台服务器的连接数可能很高,但仍然能够处理更多的请求,而另一台连接数较低的服务器可能已经达到了其性能极限。
  • 不适用于长连接:如果服务器上有大量长期活跃的连接,例如WebSocket连接,该算法可能不太适用,因为长连接不同于短暂的HTTP请求,连接数的统计可能会产生误导。
  • 无法解决服务器性能差异:虽然”最小连接数”算法可以平衡连接数,但它无法解决服务器硬件性能差异的问题。在这种情况下,可能需要其他负载均衡算法,如加权轮询,来更好地适应性能差异。

(4) 适用场景

通过服务器连接数来做负载均衡的场景。到目前为止,还没有遇到生产上使用这种算法的场景。

4.IP/URL Hash - IP/URL 散列

IP/URL 散列算法是一种根据客户端 IP 地址或 URL 来分配请求的负载均衡算法,这样相同的IP或者URL就会负载到相同的服务器上。

(1) 原理

  • 将客户端 IP 地址或 URL 散列到服务器列表中,
  • 然后将请求分配给散列值对应的服务器。

如下图:有3台服务器,分别为服务器A、服务器B和服务器C,当相同IP的客户端请求会被负载到形同的服务器列中。
在这里插入图片描述

(2) 优缺点

优点:

  • 稳定性:IP/URL Hash
    算法可以确保相同的客户端请求总是被分发到相同的服务器上。这可以提高应用程序的稳定性,因为客户端的会话数据在同一服务器上保持一致。
  • 适用于会话保持:当应用程序需要在多次请求之间保持会话状态时,IP/URL Hash
    算法非常有用。客户端在一次请求中选择的服务器会在后续请求中保持一致,确保会话数据不会丢失。
  • 负载均衡:IP/URL Hash 算法可以将特定的客户端请求均匀地分配到多个服务器上,从而实现基本的负载均衡,避免了某些服务器被过度请求。

缺点:

  • 不适用于动态环境:IP/URL Hash 算法基于客户端的 IP 地址或 URL,一旦客户端 IP 或请求的 URL
    发生变化,请求可能会被分配到不同的服务器上,导致会话数据丢失或不一致。
  • 不考虑服务器负载:IP/URL Hash 算法不考虑服务器的当前负载情况。如果某个服务器的负载过高,IP/URL Hash
    无法动态地将请求分发到负载较低的服务器上。

(3) 适用场景

  • 静态环境:在静态环境中,即客户端的 IP 地址或请求的 URL 不经常变化的情况下,IP/URL Hash 算法可以提供稳定的负载均衡。
  • 少数服务器的负载均衡:当服务器数量相对较少且不太容易动态扩展时,IP/URL Hash 算法可以用于基本的负载均衡。

5.Least Response Time - 最短响应时间

最短响应时间就是指:处理请求的响应时间最少的服务器,获取的请求就越多。直白讲就是随速度快,随就干的多。如下图:

在这里插入图片描述

(1) 适用场景

负载均衡的所有服务器,处理能力相差比较大。比如:有3台服务器,服务器A(4C8G,4个CPU,8G内存),服务器B(2C4G,2个CPU,4G内存),服务器C(1C2G,1个CPU,2G内存), 那么就可以采用这种算法,这样可以根据服务器的处理来实现动态负载。

(2) 优缺点

优点:可以充分发挥各个服务器的性能,提高服务器的利用率。

缺点:饥饿问题。比如,服务器A的性能最好,处理速度最快,那么所有的请求都会被分配到服务器A,这样服务器B和服务器C就会一直处于饥饿状态,无法处理请求。这样也就会产生不公平。

(3) 算法实现

如下伪代码:记录每台服务器以及响应时间,然后找到响应时间最短的服务器,将请求分配到该服务器上。

# 服务器列表,每个服务器表示为一个字典,包含服务器的唯一标识符和响应时间
servers = [{"id": "serverA", "response_time": 10},{"id": "serverB", "response_time": 30},{"id": "serverC", "response_time": 100},# 添加更多服务器
]# 找到响应时间最短的服务器
def find_least_response_time_server(servers):# 初始选择第一个服务器为最短响应时间服务器least_response_time_server = servers[0]# 遍历服务器列表,找到最短响应时间的服务器for server in servers:if server["response_time"] < least_response_time_server["response_time"]:least_response_time_server = serverreturn least_response_time_server# 客户端请求到来时,选择最短响应时间的服务器
def handle_client_request():least_response_time_server = find_least_response_time_server(servers)if req:least_response_time_server.handle_client_request()

需要说明的是:这只是一个简单的示例,实际的负载均衡系统可能需要更复杂的逻辑,包括定期更新服务器的响应时间、处理服务器故障等。此外,要将这种算法应用于实际生产环境,可能需要使用专门的负载均衡软件或硬件,这些工具可以自动管理服务器并提供更多功能。

(4) 适用场景

交通控制系统:在城市交通控制系统中,需要及时响应交通信号、路况和车辆检测等信息。最短响应时间算法可以帮助确保交通信号及时适应交通流量的变化。

三、总结

本文分析了五种常见的负载均衡算法,算法的实现都比较简单,在实际的生产环境中,我们可以根据自己的业务场景来选择合适的负载均衡算法。

另外,除了上面 5种算法外,还有一种其他的负载均衡算法,比如:

  • 一致性哈希:Consistent Hashing,可以参考文章:hash & 一致性hash,如何选择?
  • 加权最少连接:Weighted Least Connections,在Weighted Least Connections基础上再加权重。

在实际生产中,我们可能并不需要自己去实现这些算法,而会选择使用一些现有的框架,比如:nginx、lvs、haproxy等, 但是万变不离其宗,了解这些负载均衡算法可以帮组我们更好的去理解框架。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/2000.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙 harmonyos 线程 并发 总结 async promise Taskpool woker(二)多线程并发 Taskpool

多线程并发 并发模型是用来实现不同应用场景中并发任务的编程模型&#xff0c;常见的并发模型分为基于内存共享的并发模型和基于消息通信的并发模型。 ArkTS提供了TaskPool和Worker两种并发能力供开发者选择&#xff0c;其具体的实现特点和各自的适用场景存在差异。TaskPool&…

数据科学与大数据(3)

数据分析&#xff0c;它不应该是在一个不适合的工具下生搬硬套 工具为具体的场景服务&#xff0c;换一个场景大概率会很鸡肋&#xff0c;对于一个成熟的分析师来说&#xff0c;十八般武艺样样精通到后期为常态&#xff0c;不要产生工具上的路径依赖&#xff0c;不要想着学一个工…

IDEA更换新版本启动没反应

目前安装了新的IDEA(压缩包方式)&#xff0c;由于老版本的IDEA还在用&#xff0c;所以并没有删除&#xff0c;但是安装完后发现点击idea64.exe后没有反应&#xff0c;于是网上找了好多方法最后解决了 下面是我的解决过程 新版本&#xff1a;IntelliJIdea2024.1 老版本: Intelli…

v-for和v-if的优先级

在vue v-for和 v-if 的优先级不同。 一般情况下&#xff0c;v-if 的优先级高于 v-for。这意味着&#xff0c;如果在同一元素上同时使用 v-if 和 v-for&#xff0c;v-if 的条件判断会先执行。 这种优先级的原因是为了避免不必要的渲染开销。如果先执行 v-for 循环&#xff0c;…

ubuntu系统安装配置gitlab+Jenkins+发布持续集成持续部署保姆级教程。

1、服务器环境 名称 系统 IP 备注 gitlab ubuntu20.04.2图形化 192.168.26.130 要求有6G的内存 Jenkins Ubuntu20.04.2图形化 …

.NET/C#汇总 —— 数据库概念知识

1 为什么要⼀定要设置主键? 其实这个不是⼀定的,有些场景下,⼩系统或者没什么⽤的表,不设置主键也没关系,mysql最好是⽤ ⾃增主键,主要是以下两个原因:如果定义了主键,那么InnoDB会选择主键作为聚集索引、如果没有显 式定义主键,则innodb 会选择第⼀个不包含有NULL值…

Pytorch下张量的形状操作(详细)

目录 一、基本操作函数 二、分类&#xff1a;维度改变&#xff0c;张量变形&#xff0c;维度重排 2.1维度改变 2.2张量变形 2.3维度重排 三、实例 一、基本操作函数 在PyTorch中&#xff0c;对张量的形状进行操作是常见的需求&#xff0c;因为它允许我们重新组织、选择和…

大模型训练及推理【硬件选型指南】及 GPU 通识

我们在做大模型应用部署时&#xff08;如训练、微调、RAG&#xff09;&#xff0c;往往需要在前期就分析好硬件选型指标&#xff0c;或者我们给客户报方案之前&#xff0c;可能你已经有了一个方案&#xff0c;但是由于实践经验缺乏&#xff0c;不知道在硬件上该如何评估并上报。…

CTF练习-BUUCTF(1~25)

文章目录 Crypto题目1 一眼就解密题目解题思路flag 题目2 md5题目解题思路flag 题目3 Url编码题目解题思路flag 题目4 看我回旋踢题目解题思路1解题思路2flag 题目5 摩丝题目解题思路flag 题目6 passwd题目解题思路flag 题目7 变异凯撒题目解题思路flag 题目8 Quoted-printable…

AJAX——封装_简易axios

1.简易axios_获取身份列表 需求&#xff1a;基于Promise XHR 封装 myAxios函数&#xff0c;获取省份列表展示 步骤&#xff1a; 1.定义 myAxios函数&#xff0c;接收配置对象&#xff0c;返回Promise对象 2.发起XHR请求&#xff0c;默认请求方法为GET 3.调用成功/失败的处…

大模型日报2024-04-22

大模型日报 2024-04-22 大模型资讯 Mistral与Mixtral大型语言模型对比&#xff1a;7B、8x7B及8x22B 摘要: 最近&#xff0c;IT新闻频道广泛报道了新公开的Mixtral 8x22B模型&#xff0c;该模型在多项基准测试中超越了ChatGPT 3.5版本&#xff0c;尤其在MMLU等测试中表现突出。本…

Rust语言之简单涉猎

官方文档 简介 Rust 是一种静态类型语言。静态类型语言是指在编译时对变量和表达式进行类型检查&#xff0c;以确保类型的正确性。在 Rust 中&#xff0c;每个变量都需要在声明时指定其类型(也支持隐式声明&#xff0c;根据值判断)&#xff0c;并且在编译时会进行类型检查&am…

更全面的Embedding介绍

"Embedding"这个词在不同的上下文中有多种含义&#xff0c;以下是一些常见的解释&#xff1a; 计算机科学和人工智能&#xff1a;在机器学习和自然语言处理中&#xff0c;embedding是一种将词汇或短语映射到向量空间的技术。这些向量可以捕捉到词汇的语义含义&#x…

java中spring底层核心原理解析(2)

相关系列 java中spring底层核心原理解析&#xff08;1&#xff09;-CSDN博客 推断构造方法 spring在基于某个类生成bean的过程中&#xff0c;需要利用该学业有成的构造方法来实例化得到一个对象&#xff0c;但是如果一个类存在多个构造方法&#xff0c;spring会使用哪个呢? …

Python与数据库连接

新建表boss create table 创建表 Code import pymysqlcon pymysql.connect(hostlocalhost,\userroot,\password,\port3306,\dbbusiness) cursorcon.cursor() cursor.execute(create table if not exists boss(id int auto_increment primary key,name varchar(20)not null…

设计模式|代理模式(Proxy Pattern)

文章目录 什么是代理模式举例结构优缺点优点缺点代码示例与代理模式相近的设计模式什么是代理模式 代理模式(Proxy Pattern)是一种结构型设计模式,它允许你提供一个间接访问对象的方式,以控制对对象的访问。这种模式通常在不改变原始类代码的情况下,添加一些额外的逻辑或…

WPF2 样式布局

样式布局 WPF中的各类控件元素, 都可以自由的设置其样式。 诸如: 字体(FontFamily) 字体大小(FontSize) 背景颜色(Background) 字体颜色(Foreground) 边距(Margin) 水平位置(HorizontalAlignment) 垂直位置(VerticalAlignment) 等等。 而样式则是组织和重用以上的重要工具。…

Docker基础+虚拟化概念

目录 一、虚拟化简介 1、虚拟化概述 2、cpu的时间分片&#xff08;cpu虚拟化&#xff09; 3、cpu虚拟化性性能瓶颈 4、虚拟化工作 4.1虚拟机工作原理 4.2两大核心组件:QEMU、KVM 4.2.1QEMU&#xff1a; 4.2.2KVM&#xff1a; 5、虚拟化类型 ①全虚拟化&#xff1a; …

MySQL-数据目录

一、MySQL的主要目录结构&#xff08;MySQL 8&#xff09; [rootlocalhost ~]# find / -name mysql find: ‘/proc/30845’: 没有那个文件或目录 find: ‘/proc/30855’: 没有那个文件或目录 /etc/logrotate.d/mysql /etc/selinux/targeted/active/modules/100/mysql /etc/sel…

国内开通chatgpt plus会员方法

ChatGPT镜像 今天在知乎看到一个问题&#xff1a;“平民不参与内测的话没有账号还有机会使用ChatGPT吗&#xff1f;” 从去年GPT大火到现在&#xff0c;关于GPT的消息铺天盖地&#xff0c;真要有心想要去用&#xff0c;途径很多&#xff0c;别的不说&#xff0c;国内GPT的镜像…