负载均衡(理解/解析)

目录

什么是负载均衡

应用场景

        网络服务和应用:

        云计算和虚拟化:

负载均衡分类

        硬件负载均衡器

        软件负载均衡器

部署方式

        硬件部署:

        软件部署:

        云部署:

        路由模式:

算法实现

        轮询法(Round Robin):

        加权轮询法(Weighted Round Robin):

        随机法(Random):

        最小连接数算法(Least-Connection Scheduling):

        加权最小连接数算法(Weighted Least-Connection Scheduling):


什么是负载均衡

负载均衡(Load Balancing)是一种将工作负载(例如网络流量、数据请求、计算任务等)分配到多个计算资源(例如服务器、虚拟机、容器等)的技术。它的主要目的是优化性能、提高可靠性以及增加可扩展性。在工作环境中,负载均衡器通常位于应用程序前端,接受并分配传入的请求,通过算法确定分配请求的最佳方式,从而防止任何一个资源过载或失效导致应用程序的性能下降或停止响应。

应用场景

        网络服务和应用:

负载均衡技术广泛用于Web服务器、FTP服务器、数据库服务器等,确保它们能够处理大量并发请求,提供稳定的服务。


        云计算和虚拟化:

在云计算环境中,负载均衡用于分配虚拟机、容器等资源,确保资源的有效利用和服务的持续可用性。
大数据和分布式系统:在处理大规模数据和分析任务时,负载均衡有助于将数据和工作负载均匀分布到多个节点上,提高处理速度和效率。
在生活中,虽然不会直接用到负载均衡的概念,但类似的原理可以应用于许多场景。例如,在一个大型活动中,组织者可能会将参与者分配到不同的区域或队列中,以平衡各个区域或队列的负载,确保活动顺利进行。这种分散处理的方式与负载均衡在网络和计算环境中的应用有相似之处。

负载均衡分类

首先,从软硬件的角度来看,负载均衡可以分为硬件负载均衡和软件负载均衡。

        硬件负载均衡器

是专为负载均衡任务设计的物理设备,它利用专用硬件组件(如ASICs或FPGAs)来高效分发流量。其优点在于高性能和吞吐量,经过优化的任务处理,以及内置网络安全、监控和管理功能,能应对大量流量和多种协议。然而,硬件负载均衡器通常价格昂贵,特别是高性能型号,配置和维护也需要专业知识,且可扩展性受限。

        软件负载均衡器

则是运行在通用服务器或虚拟机上的应用程序,使用软件算法将流量分发到多个服务器或资源。其优点在于经济实惠、适应性强、易于扩展(可通过增加资源或升级硬件实现)以及灵活(可在各种平台和环境中部署)。但在高负载下,软件负载均衡器的性能可能较差,且可能影响主机系统资源,需要维护软件更新。

另外,负载均衡还可以根据分配策略的不同,分为普通负载均衡和动态负载均衡。普通负载均衡是指将用户请求均匀地分发到多个服务器,以实现服务器的负载均衡,通常采用静态的分发算法,如轮询、随机等。而动态负载均衡则是根据服务器的实时负载情况,动态地调整请求的分发策略,以保证服务器负载的均衡。每个服务器被分配一个权重值,权重越高,则分发到该服务器的请求越多。

此外,根据网络层次的不同,负载均衡还可以分为二层负载均衡(MAC)、三层负载均衡(IP)、四层负载均衡(TCP)和七层负载均衡(HTTP)。这些负载均衡类型的主要区别在于它们工作的网络层次和处理的请求类型。

至于线上与线下的分类,这更多地是指负载均衡的部署方式。线上负载均衡通常指的是在互联网环境中运行的负载均衡解决方案,而线下负载均衡则可能指的是在私有网络或企业内部环境中运行的负载均衡。

至于各种负载均衡的优缺点,除了之前提到的软硬件负载均衡的优缺点外,不同层次的负载均衡也有其特定的优缺点。例如,七层负载均衡能够基于URL或主机名进行请求分发,对于基于Web的应用非常有用,但可能增加处理延迟。而二层负载均衡则更适用于底层网络通信,但配置和管理可能更为复杂。

部署方式

        硬件部署:

使用专用设备来进行负载均衡,这种方式需要购买昂贵的硬件设备,但具有良好的性能和可靠性。对于大型企业和高流量网站来说非常适合,可以快速分配流量,提高网站的访问速度和响应时间。但硬件负载均衡的维护成本也很高,需要专业的运维人员来管理和维修设备。


        软件部署:

基于软件运行的方式,通过安装特定的软件程序来实现负载均衡。这种方式相对于硬件部署来说价格更为合理,而且配置和管理更为简单。适合中小型企业和中小流量网站。但软件负载均衡也存在一些问题,比如安全性和可靠性方面的考虑,并且其性能和稳定性受限于所选择的软件。


        云部署:

基于云计算技术的方式,将负载均衡功能放在云服务商的服务器上运行。这种方式可以根据实际需求动态调整资源,提高灵活性和可扩展性。
在负载均衡的部署中,还需要考虑其网络架构。常见的负载均衡部署模式包括:

        路由模式:

服务器的网关必须设置成负载均衡机的LAN口地址,且与WAN口分署不同的逻辑网络。这种方式对网络的改动小,能均衡任何下行流量,约60%的用户采用这种方式部署。
桥接模式:负载均衡的WAN口和LAN口分别连接上行设备和下行服务器,所有的服务器与负载均衡均在同一逻辑网络中。此模式配置简单,不改变现有网络,但由于其容错性差,一般不推荐。
服务直接返回模式:负载均衡的LAN口不使用,WAN口与服务器在同一个网络中。对于客户端而言,响应的IP是服务器自身的IP地址,返回的流量不经过负载均衡。这种模式比较适合吞吐量大特别是内容分发的网络应用,约30%的用户采用这种模式。

算法实现

        轮询法(Round Robin):

轮询法是最简单的一种负载均衡算法,它将请求按顺序轮流地分配到后端服务器上。这种算法对后端服务器的处理能力一视同仁,不考虑实际的连接数和系统负载。

package routine.LoadBalance;import java.util.LinkedList;
import java.util.List;/*** 轮询法(Round Robin)** 非常基本的实现,并没有考虑很多实际负载均衡器需要考虑的因素,* 比如服务器的健康状况、性能、权重等。* 在实际应用中,负载均衡算法通常会结合更多的信息和策略来实现更高效的负载分配。*/
public class RoundRobinLoadBalancer {private List<String> servers; // 后端服务器列表  private int currentIndex = 0; // 当前服务器索引  public RoundRobinLoadBalancer(List<String> servers) {this.servers = servers;}// 获取下一个服务器  public synchronized String getNextServer() {if (servers == null || servers.isEmpty()) {return null;}//每次被调用时,都会返回当前索引对应的服务器,并将索引加一并取模,以确保索引在服务器列表的范围内循环。String server = servers.get(currentIndex);currentIndex = (currentIndex + 1) % servers.size(); // 循环索引  return server;}public static void main(String[] args) {//创建三台服务器List<String> servers = new LinkedList<>();servers.add("server1");servers.add("server2");servers.add("server3");RoundRobinLoadBalancer loadBalancer = new RoundRobinLoadBalancer(servers);// 模拟10请求。每次请求都会调用 getNextServer 方法来获取下一个服务器,并输出请求发送到的服务器名称。for (int i = 0; i < 10; i++) {String server = loadBalancer.getNextServer();System.out.println("Request " + (i + 1) + " is sent to server: " + server);}}
}


        加权轮询法(Weighted Round Robin):

加权轮询法给每个服务器都设置了权重,配置低、负载高的服务器权重低,配置高、负载低的服务器权重高。这样,高性能的服务器能够处理更多的请求。

package routine.LoadBalance;import java.util.LinkedList;
import java.util.List;/*** 加权轮询法* 示例中并没有实现动态调整权重的功能,如根据服务器的当前连接数来调整权重。* 在实际应用中,你可能需要根据服务器的实时负载情况来动态调整权重,以达到更好的负载均衡效果*/
public class WeightedRoundRobinLoadBalancer {  private List<Server> servers; // 后端服务器列表,每个服务器带有权重  private int currentWeight; // 当前权重  private int maxWeight; // 所有服务器权重中的最大值  private int currentIndex; // 当前服务器索引  // Server类用于存储服务器信息和权重  public static class Server {  String ip;  int weight;  int currentConnections; // 当前连接数(可选,用于动态调整权重)  public Server(String ip, int weight) {  this.ip = ip;  this.weight = weight;  this.currentConnections = 0;  }  }  public WeightedRoundRobinLoadBalancer(List<Server> servers) {  this.servers = servers;  if (servers == null || servers.isEmpty()) {  throw new IllegalArgumentException("Servers list cannot be null or empty");  }  this.currentIndex = 0;  this.currentWeight = 0;  this.maxWeight = getMaxWeight(servers);  }  // 获取服务器列表中的最大权重  private int getMaxWeight(List<Server> servers) {  int max = 0;  for (Server server : servers) {  if (server.weight > max) {  max = server.weight;  }  }  return max;  }  // 获取下一个服务器  public synchronized Server getNextServer() {  if (servers == null || servers.isEmpty()) {  return null;  }  Server selectedServer = null;  while (selectedServer == null) {//currentWeight 大于或等于 maxWeightif (currentWeight >= maxWeight) {//选择当前服务器,并将 currentWeight 减去 maxWeightcurrentWeight = currentWeight - maxWeight;//索引 currentIndex 向前移动一位currentIndex = (currentIndex + 1) % servers.size();  }  if (currentIndex >= 0 && currentIndex < servers.size()) {  selectedServer = servers.get(currentIndex);  currentWeight = currentWeight + selectedServer.weight;  }  }  // 可选:更新当前服务器的连接数(用于动态调整权重)  
//         selectedServer.currentConnections++;return selectedServer;  }  public static void main(String[] args) {  List<Server> servers = new LinkedList<>();  servers.add(new Server("server1", 1));  servers.add(new Server("server2", 3));  servers.add(new Server("server3", 2));  WeightedRoundRobinLoadBalancer loadBalancer = new WeightedRoundRobinLoadBalancer(servers);  // 模拟请求  for (int i = 0; i < 10; i++) {  Server server = loadBalancer.getNextServer();  System.out.println("Request " + (i + 1) + " is sent to server: " + server.ip);  }  }  
}


        随机法(Random):

随机法通过系统的随机算法,根据后端服务器的列表大小值来随机选择其中一台服务器访问。这种方式能够随机地分配请求,但对于每台服务器的实际负载情况并无考虑。
加权随机法(Weighted Random):加权随机法类似于加权轮询法,不过在处理请求分担时是一个随机选择的过程。它根据后端服务器的配置和负载情况分配不同的权重,然后按照权重随机选择服务器。

package routine.LoadBalance;import java.util.List;
import java.util.Random;/*** 随机法* 随机法不考虑服务器的性能或负载情况,因此它可能不是最优的负载均衡策略,* 特别是在服务器之间存在较大性能差异的情况下。* 然而,对于某些简单场景或临时负载平衡,随机法可能是一个简单且有效的选择。*/
public class RandomLoadBalancer {  private List<Server> servers; // 后端服务器列表  private Random random; // 随机数生成器  // Server类用于存储服务器信息  public static class Server {  String ip;  public Server(String ip) {  this.ip = ip;  }  }  public RandomLoadBalancer(List<Server> servers) {  if (servers == null || servers.isEmpty()) {  throw new IllegalArgumentException("Servers list cannot be null or empty");  }  this.servers = servers;  this.random = new Random();  }  // 获取下一个服务器  public Server getNextServer() {  if (servers == null || servers.isEmpty()) {  return null;  }  // 随机选择一个服务器索引  int index = random.nextInt(servers.size());  // 返回该索引对应的服务器  return servers.get(index);  }  public static void main(String[] args) {  List<Server> servers = List.of(  new Server("server1"),  new Server("server2"),  new Server("server3")  );  RandomLoadBalancer loadBalancer = new RandomLoadBalancer(servers);  // 模拟请求  for (int i = 0; i < 10; i++) {  Server server = loadBalancer.getNextServer();  System.out.println("Request " + (i + 1) + " is sent to server: " + server.ip);  }  }  
}


        最小连接数算法(Least-Connection Scheduling):

该算法是一种动态调度算法,通过服务器中当前所活跃的连接数来估计服务器的负载情况,把新的连接请求分配到当前连接数最小的服务器。这种算法能更好地利用后端服务器的处理能力,但在服务器处理能力差异大的情况下可能并不理想。

package routine.LoadBalance;import java.util.*;/*** 最小连接数算法* 没有考虑线程安全问题。* 在并发环境中,connectionCounts 的更新需要同步,以避免竞态条件。* 可以使用 synchronized 块、ReentrantLock 或其他并发控制机制来实现线程安全。* 此外,这个示例也没有处理服务器不可用的情况,实际应用中可能需要添加服务器健康检查逻辑。*/
public class LeastConnectionsLoadBalancer {private List<Server> servers; // 后端服务器列表  private Map<Server, Integer> connectionCounts; // 服务器当前连接数映射  // Server类用于存储服务器信息和当前连接数  public static class Server {String ip;int currentConnections;public Server(String ip) {this.ip = ip;this.currentConnections = 0;}// 增加连接数  public void incrementConnectionCount() {this.currentConnections++;}// 减少连接数  public void decrementConnectionCount() {this.currentConnections--;}}public LeastConnectionsLoadBalancer(List<Server> servers) {if (servers == null || servers.isEmpty()) {throw new IllegalArgumentException("Servers list cannot be null or empty");}this.servers = servers;this.connectionCounts = new HashMap<>();for (Server server : servers) {connectionCounts.put(server, 0);}}// 获取下一个服务器,使用最小连接数算法  public Server getNextServer() {if (servers == null || servers.isEmpty()) {return null;}Server leastLoadedServer = null;int minConnections = Integer.MAX_VALUE;// 遍历服务器列表,找到连接数最少的服务器  for (Server server : servers) {int currentConnections = connectionCounts.get(server);if (currentConnections < minConnections) {minConnections = currentConnections;leastLoadedServer = server;}}// 如果没有找到服务器或者所有服务器连接数相同,则随机选择一个  if (leastLoadedServer == null) {Collections.shuffle(servers);leastLoadedServer = servers.get(0);}// 更新连接数  connectionCounts.put(leastLoadedServer, minConnections + 1);return leastLoadedServer;}// 当请求处理完成时,减少服务器的连接数  public void processCompleted(Server server) {if (server != null && connectionCounts.containsKey(server)) {connectionCounts.put(server, connectionCounts.get(server) - 1);}}public static void main(String[] args) {List<Server> servers = Arrays.asList(new Server("server1"),new Server("server2"),new Server("server3"));LeastConnectionsLoadBalancer loadBalancer = new LeastConnectionsLoadBalancer(servers);// 模拟并发请求,实现连接数最小取值for (int i = 0; i < 10; i++) {Thread thread = new Thread(() -> {Server server = loadBalancer.getNextServer();System.out.println("线程:" + Thread.currentThread().getName() + " is sent to server: " + server.ip);// 模拟请求处理完成后减少连接数loadBalancer.processCompleted(server);});thread.start();}}
}


        加权最小连接数算法(Weighted Least-Connection Scheduling):

这种算法用相应的权值表示各个服务器的处理性能,具有较高权值的服务器将承受较大比例的活动连接负载。调度器可以自动问询服务器的负载情况,并动态地调整其权值。

package routine.LoadBalance;import java.util.*;/*** 加权最小连接数算法* 考虑了服务器的处理能力差异,为每个服务器分配不同的权重,* 权重通常反映了服务器的处理能力。权重较高的服务器可以处理更多的连接。*/
public class WeightedLeastConnectionsLoadBalancer {private List<WeightedServer> servers; // 后端服务器列表  private Map<WeightedServer, Integer> connectionCounts; // 服务器当前连接数映射  // WeightedServer类用于存储服务器信息、权重和当前连接数  public static class WeightedServer {String ip;int weight;int currentConnections;public WeightedServer(String ip, int weight) {this.ip = ip;this.weight = weight;this.currentConnections = 0;}// 增加连接数  public void incrementConnectionCount() {this.currentConnections++;}// 减少连接数  public void decrementConnectionCount() {this.currentConnections--;}// 获取有效连接数(考虑权重)  这里需要计算考量public int getEffectiveConnections() {return currentConnections * weight;}}public WeightedLeastConnectionsLoadBalancer(List<WeightedServer> servers) {if (servers == null || servers.isEmpty()) {throw new IllegalArgumentException("Servers list cannot be null or empty");}this.servers = servers;this.connectionCounts = new HashMap<>();for (WeightedServer server : servers) {connectionCounts.put(server, 0);}}// 获取下一个服务器,使用加权最小连接数算法  public WeightedServer getNextServer() {if (servers == null || servers.isEmpty()) {return null;}WeightedServer leastLoadedServer = null;int minEffectiveConnections = Integer.MAX_VALUE;// 遍历服务器列表,找到有效连接数最少的服务器for (WeightedServer server : servers) {int effectiveConnections = connectionCounts.get(server);
//            int effectiveConnections = server.getEffectiveConnections();if (effectiveConnections < minEffectiveConnections) {minEffectiveConnections = effectiveConnections;leastLoadedServer = server;}}// 如果没有找到服务器,则随机选择一个  if (leastLoadedServer == null) {Collections.shuffle(servers);leastLoadedServer = servers.get(0);}// 更新连接数connectionCounts.put(leastLoadedServer, connectionCounts.get(leastLoadedServer) + 1);return leastLoadedServer;}// 当请求处理完成时,减少服务器的连接数  public void processCompleted(WeightedServer server) {if (server != null && connectionCounts.containsKey(server)) {connectionCounts.put(server, connectionCounts.get(server) - 1);}}public static void main(String[] args) {List<WeightedServer> servers = Arrays.asList(new WeightedServer("server1", 2),new WeightedServer("server2", 3),new WeightedServer("server3", 1));WeightedLeastConnectionsLoadBalancer loadBalancer = new WeightedLeastConnectionsLoadBalancer(servers);// 模拟请求  for (int i = 0; i < 10; i++) {Thread thread = new Thread(() -> {WeightedServer server = loadBalancer.getNextServer();System.out.println("线程:" + Thread.currentThread().getName() + " is sent to server: " + server.ip);// 模拟请求处理完成后减少连接数loadBalancer.processCompleted(server);});thread.start();}}
}


除此之外,还有源地址哈希法等负载均衡算法,通过对发送请求的客户端的IP地址进行哈希运算,然后选择结果对应的服务器来处理请求,这样可以保证来自同一客户端的请求总是被分配到同一台服务器上,有助于保持会话的持续性。

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

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

相关文章

【详细介绍下火绒安全】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

如何做信创测试

信创测试是一种系统化的方法&#xff0c;旨在评估和验证创意和创新项目的潜力和可行性。进行信创测试可以帮助企业在投入大量资源之前&#xff0c;对创意进行客观、科学的评估&#xff0c;以减少失败的风险并最大化成功的可能性。以下是一般性的信创测试步骤&#xff1a; 确定…

Web前端 JavaScript笔记4

1、元素内容 属性名称说明元素名.innerText输出一个字符串&#xff0c;设置或返回元素中的内容&#xff0c;不识别html标签元素名.innerHTML输出一个字符串&#xff0c;设置或返回元素中的内容&#xff0c;识别html标签元素名.textContent设置或返回指定节点的文本内容&#x…

Pygame经典游戏:贪吃蛇

------------★Pygame系列教程★------------ Pygame经典游戏&#xff1a;贪吃蛇 Pygame教程01&#xff1a;初识pygame游戏模块 Pygame教程02&#xff1a;图片的加载缩放旋转显示操作 Pygame教程03&#xff1a;文本显示字体加载transform方法 Pygame教程04&#xff1a;dra…

【uniapp】vscode安装插件、ts校验、允许json文件注释

1、vscode安装的插件&#xff1a; uni-create-viewuni-hlperuniapp小程序扩展 2、ts校验 安装插件&#xff1a; pnpm i -D types/wechat-miniprogram uni-helper/uni-app-types配置tsconfig.json {"extends": "vue/tsconfig/tsconfig.json","compi…

基于数据库现有表导出为设计文档

1.查询 SELECTCOLUMN_NAME 字段名,COLUMN_COMMENT 字段描述,COLUMN_TYPE 字段类型,false as 是否为主键 FROMINFORMATION_SCHEMA.COLUMNS wheretable_NAME region -- 表名2.查询结果 3.导出为excel

Python(11):网络编程

文章目录 一、一些基本概念二、软件的开发架构&#xff08;c/s架构和b/s架构&#xff09;三、OSI模型四、socket套接字编程1.socket编程过程2.python中的socket编程 一、一些基本概念 来了解一些网络的基本概念 名词解释IP&#xff08;互联网协议地址&#xff09;IP用来标识网…

抖音扫码登录

抖音扫码登录&#xff0c;ck可以点赞关注上传视频 主要涉及参数: bd_ticket_guard_client_data bd_ticket_guard_server_data bd_ticket_guard_ree_public_key bd_ticket_crypt_cookie x–secadk–csrf–token req_sign abogus ts_sign ticket {"is_digg":…

MySQL之锁详细总结

介绍 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中&#xff0c;除传统的计算资源&#xff08;CPU、RAM、I/O&#xff09;的争用外&#xff0c;数据也是一种供多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题&…

记一次事件到供应链的顶级拉扯

前言 某天&#xff0c;夜里3点 天刚蒙蒙亮 开局&#xff1a;我有一个朋友~ 看不懂发的什么意思&#xff0c;再仔细看看&#xff0c;懂了! 闲言少叙&#xff0c;遇事不决先上bp&#xff0c;启动&#xff01; 进去之后发现基本没什么实际功能点&#xff0c;像假的一样。注意这里…

DC-5渗透测试复现

DC-5渗透测试复现 目的&#xff1a; 获取最高权限以及5个flag 过程&#xff1a; 信息打点-文件包含漏洞-弹shell- scren-4.0.5提权 环境&#xff1a; 攻击机&#xff1a;kali(192.168.85.136) 靶机&#xff1a;DC_3(192.168.85.134) 复现&#xff1a; 一.信息收集 nma…

分享|为什么说Temu项目是蓝海项目?

在当今日新月异的互联网行业中&#xff0c;Temu项目以其独特的商业模式和前瞻性的市场布局&#xff0c;迅速崛起成为一颗耀眼的新星。它被业内普遍认为是一片尚未被完全开发的蓝海&#xff0c;具有巨大的市场潜力和发展空间。那么&#xff0c;为什么说Temu项目是蓝海项目呢? 首…