负载均衡的原理及算法

news2024/9/24 9:21:04

在这里插入图片描述

一、定义

负载均衡(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 = 0
    else:
      # 指针+1
      current_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 = 0
    else:
      # 指针+1
      current_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] += 1
    return server
  else:
    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 = server

    return 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.coloradmin.cn/o/1616135.html

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

相关文章

【链表】Leetcode 两两交换链表中的结点

题目讲解 24. 两两交换链表中的节点 算法讲解 只需要模拟这个过程就行了&#xff0c;但是需要注意空指针的问题&#xff0c;特别是nnext指针 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), ne…

“AI 程序员入职系列”第二弹:如何利用通义灵码光速改写项目编程语言?

通义灵码入职阿里云云原生团队后&#xff0c;已经展示过 Ta 生成单元测试和自动生成代码的强大实力。今天&#xff0c;阿里云后端工程师云徊将从项目开发的实际需求出发&#xff0c;演示通义灵码在开发工作中可提供的帮助。 通义灵码在 Git 开发项目中起到了哪些作用&#xff…

IntelliJ IDEA - Lombok supports: OpenJDK javac, ECJ

问题描述 java: You arent using a compiler supported by lombok, so lombok will not work and has been disabled.Your processor is: com.sun.proxy.$Proxy26Lombok supports: OpenJDK javac, ECJ 解决方案 在 IDEA 设置中 File -> Settings 中找到配置如下&#xff1…

医学影像增强:空间域方法与频域方法等

医学影像图像增强是一项关键技术,旨在改善图像质量,以便更好地进行疾病诊断和评估。增强方法通常分为两大类:空间域方法和频域方法。 一、 空间域方法 空间域方法涉及直接对医学影像的像素值进行操作,以提高图像的视觉质量。以下是一些常用的空间域方法: 对比度调整:通过…

【Web】2022DASCTF MAY 出题人挑战赛 题解(全)

目录 Power Cookie 魔法浏览器 getme hackme fxxkgo ezcms Power Cookie 点击login in by guest后响应头给set了一个admin0的cookie 魔法浏览器 看到魔法UA 直接在console输出即可 改UA&#xff0c;拿到flag getme 右键查看源码 抓包看到响应头&#xff0c;Apache版本…

文旅IP孵化打造抖音宣传推广运营策划方案

【干货资料持续更新&#xff0c;以防走丢】 文旅IP孵化打造抖音宣传推广运营策划方案 部分资料预览 资料部分是网络整理&#xff0c;仅供学习参考。 PPT可编辑&#xff08;完整资料包含以下内容&#xff09; 目录 文旅IP抖音运营方案 1. 项目背景与目标 - 背景&#xff1a…

uniapp IOS上架AppStore因打开相机、相册提示不明确被拒

被拒原因&#xff1a; 提示说红框标识的权限说明不够明确&#xff0c;否则用户不知道问什么要访问这个权限。 解决方案&#xff1a; 只需要我们再次打包ios的时候在manifest.json文件里&#xff0c;所用到权限的地方重新填写一下使用说明&#xff0c;再次打包提交审核即可。

Jenkins CI/CD 持续集成专题一 Jenkins的安装和配置

一 jenkins 官方教程 安装Jenkins 二 安装 2.1 安装方式一 通过安装包的package方式安装 第一步下载链接&#xff1a; Download the latest package 第二步操作方式&#xff1a;打开包并按照说明操作即可安装 2.2 安装方式二 brew安装 第一 安装最新版本jenkins brew in…

【Spring进阶系列丨最终篇】一文详解Spring中的事务控制

0、说明 本篇文章是【Spring进阶系列】专栏的最后一篇文章&#xff0c;至此&#xff0c;我们对Spring的学习就告一段落&#xff0c;接下来我会持续更新【SpringSpringMVCMyBatis整合】专栏&#xff0c;欢迎免费订阅&#xff01; 文章目录 0、说明 一、Spring事务控制1、事务的环…

集创赛Robei杯——Robei八角板7020简介

官方介绍 若贝八角板是一款FPGA开发板&#xff0c;可以用于系统设计与教育教学、竞赛、IC验证、系统控制、挖矿、云计算等用途&#xff0c;板子整体呈现正八角形&#xff0c;尺寸非常小&#xff0c;68x68mm&#xff0c;手掌心大小。虽然板子很小&#xff0c;但是功能齐全&#…

数据结构(邓俊辉)学习笔记——向量vector_01_接口与实现

文章目录 0.意图1、概述2 从数组到向量3 向量ADT接口4 Vector 模板类5 构造与析构5.1默认构造方法5.2基于复制的构造方法5.3 析构方法 0.意图 一方面是将工作学习中零星的知识点串起来&#xff0c;另一方面向量是其他数据类型的基础&#xff0c;比如栈队列等&#xff0c;所以基…

五种服务异步通信(MQ)-详解、代码案例

简介&#xff1a;本篇文章主要是介绍了常用的异步通信原理&#xff0c;主要是RabbitMQ技术 目录 1、初始MQ&#xff08;异步通讯&#xff09; 1.1 同步通讯 1.2 异步通讯 1.3 MQ常见框架 2、RabbitMQ快速入门 2.1 RabbitMQ概述和安装 2.2 常见消息模型 2.3 快速入门 3、…

【华为 ICT HCIA eNSP 习题汇总】——题目集18

1、SSH默认工作使用的TCP端口号是&#xff08;&#xff09;。 A、20 B、21 C、22 D、23 考点&#xff1a;①传输层 ②应用层 解析&#xff1a;&#xff08;C&#xff09; SSH为建立在应用层和传输层上的安全协议&#xff0c;是对TCP/IP协议的传输层以上的SSH会话流程进行加密的…

数字时代的社交王者:探索Facebook的社交帝国

引言&#xff1a;社交媒体的霸主 在数字化浪潮席卷全球的当下&#xff0c;社交媒体已然成为人们日常生活中不可或缺的一部分&#xff0c;而Facebook则是这个领域的不二之选。作为全球最大的社交网络&#xff0c;Facebook不仅拥有庞大的用户群体&#xff0c;更在技术创新、社会…

System Dashboard for Mac:强大的系统监控与管理工具

System Dashboard for Mac是一款专为苹果电脑设计的系统监控与管理工具&#xff0c;以其直观易用的界面和全面的功能&#xff0c;深受用户喜爱。 System Dashboard for Mac v1.10.11激活版下载 这款软件能够实时监测系统的重要参数&#xff0c;包括CPU使用率、内存利用率、硬盘…

Acer宏碁掠夺者战斧300笔记本电脑PH315-52工厂模式原装Win10系统安装包 恢复出厂开箱状态 带恢复重置

宏碁掠夺者PH315-52原厂Windows10工厂包镜像下载&#xff0c;预装oem系统 链接&#xff1a;https://pan.baidu.com/s/1grmJzz6nW1GOaImY_ymXGw?pwdi286 提取码&#xff1a;i286 原厂W10系统自带所有驱动、PredatorSense风扇键盘控制中心、Office办公软件、出厂主题壁纸、系统…

OpenHarmony开发实例:【电话簿联系人Contacts】

样例简介 Contacts应用是基于OpenHarmony SDK开发的安装在润和HiSpark Taurus AI Camera(Hi3516d)开发板标准系统上的应用&#xff1b;应用主要功能是展示联系人列表&#xff0c;并点击某一列弹出联系人详细信息&#xff1b; 运行效果 样例原理 样例主要有一个list组件和dia…

unknown option ‘--variant=xxx‘

进行react native开发&#xff0c;启动项目时&#xff0c;出现如上报错时&#xff0c;试着用‘mode’代替variant即可 详细说明&#xff1a; 修改scripts命令&#xff0c;加入–variantdevDebug 终端运行对应命令,报如下的错 error: unknown option --variantdevDebug如图&am…

个人网站的SEO优化系列——如何实现搜索引擎的收录

如果你自己做了一个网站&#xff0c;并且想让更多的人知道你的网站&#xff0c;那么无非就是两种途径 一、自己进行宣传&#xff0c;或者花钱宣传 二、使用搜索引擎的自然流量 而如果搜索引擎都没有收录你的站点&#xff0c;别说是自然流量&#xff0c;就算是使用特定语句【sit…

在誉天学习云计算HCIE,担心考试考不过?

誉天定制化课程内容覆盖了所有考试重点&#xff0c;可以系统地掌握理论与实践知识。 对于笔试&#xff0c;类似于备考驾照理论学习阶段&#xff0c;誉天为大家提供在线模拟测试系统&#xff0c;帮助大家掌握云计算笔试考点。笔试通过后&#xff0c;18个月内&#xff08;一年半…