每个Java程序员都必须知道的四种负载均衡算法
前言
一般来说,我们在设计系统的时候,为了系统的高扩展性,会尽可能的创建无状态的系统,这样我们就可以采用集群的方式部署,最终很方便的根据需要动态增减服务器数量。但是,要使系统具有更好的可扩展性,除了无状态设计之外,还要考虑采用什么负载均衡算法,本文就带领大家认识以下常见的4种负载均衡算法。
欢迎关注个人公众号『JAVA旭阳』交流沟通
什么是负载均衡
负载均衡是指多台服务器以对称的方式组成一个服务器集群。每台服务器的地位相当(但不同的服务器可能性能不同),可以独立提供服务,无需其他服务器的辅助。为了保证系统的可扩展性,需要有一种算法能够将系统负载平均分配给集群中的每台服务器。这种算法称为负载均衡算法。负责执行负载均衡算法并平均分配请求的服务器称为负载均衡器。
随机算法
随机算法非常简单,该算法的核心是通过随机函数随机获取一个服务器进行访问。假设我们现在有四台服务器,192.168.1.1~ 192.168.1.4
, 该算法用java实现大致如下:
public class RandomTest {
private static final List<String> servers = Arrays.asList("192.168.1.1", "192.168.1.2", "192.168.1.3", "192.168.1.4");
public static String getServer() {
Random random = new Random();
int index = random.nextInt(servers.size());
return servers.get(index);
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
String server = getServer();
System.out.println("select server: "+server);
}
}
}
当样本较小时,算法可能分布不均匀,但根据概率论,样本越大,负载会越均匀,而负载均衡算法本来就是为应对高并发场景而设计的。该算法的另一个缺点是所有机器都有相同的访问概率, 如果服务器性能不同,负载将不平衡。
轮询算法
Round-Robin
轮询算法是另一种经典的负载均衡算法。请求以循环的方式分发到集群中的所有服务器。同理,对于上述四台服务器,假设客户端向集群发送10个请求,则请求分布将如下图所示:
在十个请求中,第一、第五和第九个请求将分配给192.168.1.1
,第二、第六和第十个请求将分配给192.168.1.2
,依此类推。我们可以看到round-robin
算法可以在集群中均匀的分配请求。但是,该算法具有与随机算法相同的缺点,如果服务器性能不同,负载将不平衡,因此需要加权轮询算法。
加权轮询算法
Weighted Round-Robin
加权轮询算法是在round-robin
算法的基础上根据服务器的性能分配权重。服务器能支持的请求越多,权重就越高,分配的请求也就越多。对于同样的10个请求,使用加权轮询算法的请求分布会如下图所示:
可以看到192.168.1.4
权重最大,分配的请求数最多。看一下使用Java简单实现的以下加权循环算法。
public class RoundRobinTest {
public class Node{
private String ip;
private Integer weight;
private Integer currentWeight;
public Node(String ip,Integer weight) {
this.ip = ip;
this.weight = weight;
this.currentWeight = weight;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
public Integer getCurrentWeight() {
return currentWeight;
}
public void setCurrentWeight(Integer currentWeight) {
this.currentWeight = currentWeight;
}
}
List<Node> servers = Arrays.asList(
new Node("192.168.1.1",1),
new Node("192.168.1.2",2),
new Node("192.168.1.3",3),
new Node("192.168.1.4",4));
private Integer totalWeight;
public RoundRobinTest() {
this.totalWeight = servers.stream()
.mapToInt(Node::getWeight)
.reduce((a,b)->a+b).getAsInt();
}
public String getServer() {
Node node = servers.stream().max(Comparator.comparingInt(Node::getCurrentWeight)).get();
node.setCurrentWeight(node.getCurrentWeight()-totalWeight);
servers.forEach(server->server.setCurrentWeight(server.getCurrentWeight()+server.getWeight()));
return node.getIp();
}
public static void main(String[] args) {
RoundRobinTest roundRobinTest = new RoundRobinTest();
for (int i = 0; i < 10; i++) {
String server = roundRobinTest.getServer();
System.out.println("select server: "+server);
}
}
该算法的核心是的动态计算currentWeight
。每个服务器被选中后,currentWeight
需要减去所有服务器的权重之和,这样可以避免权重高的服务器一直被选中。权重高的服务器有更多的分配请求,请求可以平均分配给所有服务器。
哈希算法
哈希算法,顾名思义,就是利用哈希表根据 计算出请求的路由hashcode%N。这里hashcode代表哈希值,N代表服务器数量。该算法的优点是实现起来非常简单。具体实现如下:
rivate static final List<String> servers = Arrays.asList("192.168.1.1", "192.168.1.2", "192.168.1.3", "192.168.1.4");
public static String getServer(String key) {
int hash = key.hashCode();
int index = hash%servers.size();
return servers.get(index);
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
String server = getServer(String.valueOf(i));
System.out.println("select server: "+server);
}
}
哈希算法在很多缓存分布式存储系统中很常见,比如Memorycached
和Redis
,但是一般不会用到上面的哈希算法,而是优化后的一致性哈希算法。
总结
本文总结了负载均衡常见的4种算法,我们可以发现nginx
或者spring cloud
中的ribbon
都使用到了这样的算法思想,我们可以根据自己的业务场景选择合适算法。
欢迎关注个人公众号『JAVA旭阳』交流沟通
每个Java程序员都必须知道的四种负载均衡算法的更多相关文章
- 《JAVA 程序员面试宝典(第四版)》读书笔记之前言
工作五年了一直在小的软件公司混,总感觉自己的专业知识没有太大的提升.当然了中间也换了一两家公司,面试的公司就很多家,总感觉正规的软件公司(无论大小)对于基础知识的考核都非常重视,而不管你说你之前服务过 ...
- Java程序员都应该去使用一下这款强大的国产工具类库
这不是标题党,今天给大家推荐一个很棒的国产工具类库:Hutool.可能有很多朋友已经知道这个类库了,甚至在已经在使用了,如果你还没有使用过,那不妨去尝试一下,我们项目组目前也在用这个.这篇文章来简单介 ...
- 2020年薪30W的Java程序员都要求熟悉JVM与性能调优!
前言 作为Java程序员,你有没有被JVM伤害过?面试的时候是否碰到过对JVM的灵魂拷问? 一.JVM 内存区域划分 1.程序计数器(线程私有) 程序计数器(Program Counter Reg ...
- Java程序员都需要懂的「反射」
前言 只有光头才能变强. 文本已收录至我的GitHub精选文章,欢迎Star:https://github.com/ZhongFuCheng3y/3y 今天来简单写一下Java的反射.本来没打算写反射 ...
- 99.9%的Java程序员都说不清的问题:JVM中的对象内存布局?
本文转载自公众号:石彬的架构笔记,阅读大约需要8分钟. 作者:李瑞杰 目前就职于阿里巴巴,资深 JVM 研究人员 在 Java 程序中,我们拥有多种新建对象的方式.除了最为常见的 new 语句之外,我 ...
- 90% 的 Java 程序员都说不上来的为何 Java 代码越执行越快(1)- JIT编译优化
麻烦大家帮我投一票哈,谢谢 经常听到 Java 性能不如 C/C++ 的言论,也经常听说 Java 程序需要预热,那么其中主要原因是啥呢? 面试的时候谈到 JVM,也有很多面试官喜欢问,为啥 Java ...
- 90% 的 Java 程序员都说不上来的为何 Java 代码越执行越快(2)- TLAB预热
经常听到 Java 性能不如 C/C++ 的言论,也经常听说 Java 程序需要预热,那么其中主要原因是啥呢? 面试的时候谈到 JVM,也有很多面试官喜欢问,为啥 Java 程序越执行越快呢? 一般人 ...
- 看完这篇微服务架构设计思想,90%的Java程序员都收藏了
本博客强烈推荐: Java电子书高清PDF集合免费下载 https://www.cnblogs.com/yuxiang1/p/12099324.html 微服务 软件架构是一个包含各种组织的系统组织, ...
- 阿里面试Java程序员都问些什么?
刚开始也是小白,也是一步步成成起来的.需要提的一点是,你将来是需要靠这个吃饭的,所以请对找工作保持十二分的热情,而且越早准备越好. 阿里一面 一面是在上午9点多接到支付宝的面试电话的,因为很期望能够尽 ...
- Java程序员都要懂得知识点:反射
摘要:Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语 ...
随机推荐
- NLP之基于logistic回归的文本分类
数据集下载: 链接:https://pan.baidu.com/s/17EL37CQ-FtOXhtdZHQDPgw 提取码:0829 逻辑斯蒂回归 @ 目录 逻辑斯蒂回归 1.理论 1.1 多分类 1 ...
- 【JVM】关于JVM,你需要掌握这些 | 一文彻底吃透JVM系列
写在前面 最近,一直有小伙伴让我整理下关于JVM的知识,经过十几天的收集与整理,初版算是整理出来了.希望对大家有所帮助. JDK 是什么? JDK 是用于支持 Java 程序开发的最小环境. Java ...
- 「浙江理工大学ACM入队200题系列」问题 E: 零基础学C/C++78——求奇数的乘积
本题是浙江理工大学ACM入队200题第八套中的E题 我们先来看一下这题的题面. 题面 输入 输入数据包含多个测试实例,每个测试实例占一行,每行的第一个数为n,表示本组数据一共有n个,接着是n个整数,你 ...
- 如何避免由 Web 字体引起的布局偏移
前言 一些布局上的完全加载前后的变化很容易解决:为动态元素预先分配正确的空间,在图像上使用宽度和高度属性,并优先考虑 HTML 文档中的可见元素.但是,导致布局偏移的还有一个难以解决的问题:无样式文本 ...
- 解决Halcon转C#时,图像显示的问题
不知道大家在使用Halcon进行图像处理,由于要连续处理多张图片,转为C#代码的时候,使用了Halcon控件显示图像,但是运行的时候,中间的其他图片没有显示在控件上,之前我一直以为是运行速度快导致看不 ...
- Go实现常用软件设计模式二:工厂模式
目录: 举个栗子 概念介绍 使用场景 1.举个栗子 类图 ``` @startuml'https://plantuml.com/class-diagramclass Elephant { String ...
- 【Java集合框架002】原理层面:HashMap全解析
一.前言 二.HashMap 2.1 HashMap数据结构 + HashMap线程不安全 + 哈希冲突 2.1.1 HashMap数据结构 学习的时候,先整体后细节,HashMap整体结构是 底层数 ...
- codeforces补题计划
11.15 Codeforces Round #833 (Div. 2) 知识点: D:高位和对低位无影响 E:笛卡尔树上dp 补题传送门
- Pycharm2022.1.3安装教程(包含基础使用配置)
pycharm的下载安装及使用 以我的Pycharm2022.1.3为例 首先去官网下载professtional(专业版)版本 2022.1.3版本Pycharm软件 https://www.jet ...
- 我开发的开源项目,让.NET7中的EFCore更轻松地使用强类型Id
在领域驱动设计(DDD)中,有一个非常重要的概念:"强类型Id".使用强类型Id来做标识属性的类型会比用int.Guid等通用类型能带来更多的好处.比如有一个根据根据Id删除用户的 ...