一、概述
1.1什么是负载均衡
lb,既负载均衡(load balancer),是高并发、高可用系统必不可少的关键组件,其目标是尽力将网络流量平均分发到多个服务器上,以提高系统整体的响应速度和可用性。
1.2负载均衡的分类
硬件负载均衡
硬件负载均衡:一般是在定制处理器上运行的独立负载均衡服务器,价格昂贵,土豪专属。
硬件负载均衡的主流产品:f5big-ip,citrix(思杰)netscaler
硬件负载均衡优点:
- 功能强大:支持全局负载均衡并提供较全面的、复杂的负载均衡算法。
- 性能强悍:硬件负载均衡由于是在专用处理器上运行,因此吞吐量大,可支持单机百万以上的并发。
- 安全性高:往往具备防火墙,防 ddos 攻击等安全功能。
硬件负载均衡缺点:
- 成本昂贵:购买和维护硬件负载均衡的成本都很高。
- 扩展性差:当访问量突增时,超过限度不能动态扩容。
软件负载均衡
软件负载均衡从软件层面实现负载均衡,一般可以在任何标准物理设备上运行,
软件负载均衡主流产品:nginx、haproxy、lvs。
- lvs可以作为四层负载均衡器,其负载均衡的性能优于nginx。
- haproxy可以作为http和tcp负载均衡器。
- nginx、haproxy可以作为四层或七层负载均衡器。
软件负载均衡优点:
- 成本低廉:只要每个liunx服务器,然后装上nginx或其他负载均衡软件即可。
- 灵活:7层和4层负载均衡可以根据业务进行选择,有可以根据业务进行比较方便的扩展,比如:由于业务特殊需要做一些定制化的功能。
- 扩展性好:适应动态变化,可以通过添加软件负载均衡实例,动态扩展到超出初始容量的能力
软件负载均衡缺点:
- 性能一般:比起硬件来说支撑并发数不大。
- 功能没有硬件强大
- 安全性没有硬件负载均衡高
1.3ribbon(过时,了解即可)
spring cloud ribbon是基于netflix ribbon实现的一套客户端负载均衡的工具。
简单的说,ribbon是netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出load balancer(简称lb)后面所有的机器,ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们很容易使用ribbon实现自定义的负载均衡算法。
1.4loadbalancer
1.5负载均衡算法
负载均衡算法是负载均衡服务核心中的核心。负载均衡产品多种多样,但是各种负载均衡算法原理是共性的。负载均衡算法有很多种,分别适用于不同的应用场景,本文仅介绍最为常见的负载均衡算法的特性及原理:轮询、随机、最小活跃数、源地址哈希、一致性哈希。
轮询(random)
将请求按顺序轮流地分配到每个节点上,不关心每个节点实际的连接数和当前的系统负载。
优点:简单高效,易于水平扩展,每个节点满足字面意义上的均衡;
缺点:没有考虑机器的性能问题,集群性能瓶颈更多的会受性能差的服务器影响。
随机
将请求随机分配到各个节点。由概率统计理论得知,随着客户端调用服务端的次数增多,其实际效果越来越接近于平均分配,也就是轮询的结果。
动态均衡算法
-
最小连接数法
根据每个节点当前的连接情况,动态地选取其中当前积压连接数最少的一个节点处理当前请求,尽可能地提高后端服务的利用效率,将请求合理地分流到每一台服务器。
优点:动态,根据节点状况实时变化;
缺点:提高了复杂度,每次连接断开需要进行计数;
实现:将连接数的倒数当权重值。
-
最快响应速度法
根据请求的响应时间,来动态调整每个节点的权重,将响应速度快的服务节点分配更多的请求,响应速度慢的服务节点分配更少的请求,俗称能者多劳,扶贫救弱。
优点:动态,实时变化,控制的粒度更细,跟灵敏;
缺点:复杂度更高,每次需要计算请求的响应速度;
实现:可以根据响应时间进行打分,计算权重。
-
观察模式法
观察者模式是综合了最小连接数和最快响应度,同时考量这两个指标数,进行一个权重的分配
源地址哈希
根据客户端的ip地址,通过哈希计算得到一个数值,用该数值对服务器节点数进行取模,得到的结果便是要访问节点序号。采用源地址哈希法进行负载均衡,同一ip地址的客户端,当后端服务器列表不变时,它每次都会落到到同一台服务器进行访问。
优点:相同的ip每次落在同一个节点,可以人为干预客户端请求方向;
缺点:如果某个节点出现故障,会导致这个节点上的客户端无法使用,无法保证高可用。当某一用户成为热点用户,那么会有巨大的流量涌向这个节点,导致冷热分布不均衡,无法有效利用起集群的性能。所以当热点事件出现时,一般会将源地址哈希法切换成轮询法。
一致性哈希
主要的特点就是hash环,我们的请求可以构建成一个hash环,按照顺时针记录hash和请求。当我们的服务挂了a时,我们只需要将a的请求交给a后面的b处理;当我们需要增加服务器c时,我们只需要在hash环上划一块范围,然后交给c;这样就可以实现动态的扩容和缩容。一致性哈希用于解决分布式缓存系统中的节点选择和在增删服务器后,节点减少带来的数据缓存的消失与重新分配问题。
二、实战
2.1idea同一套代码,运行多个不同端口的服务
edit configurations
点击加号,然后点击springboot
勾选设置
设置
allow instances(允许开启多个实例)
add vm options (开启虚拟机选项)
-dserver.port=3399 (设置实例端口)
-dxxl.job.executor.port=9998(设置端口)我这里因为配置了xxl-job所以需要配置,可以不用写
填写下图中的1,2,3,其中2的端口号与原来的不一样即可
2.2consu数据持久化配置
2.3负载均衡实现
配置
<dependency>
<groupid>org.springframework.cloud</groupid>
<artifactid>spring-cloud-starter-loadbalancer</artifactid>
</dependency>
原理
@resource
private discoveryclient discoveryclient;
@getmapping("/consumer/discovery")
@operation(summary = "查询")
public string discovery()
{
list<string> services = discoveryclient.getservices();
for (string element : services) {
system.out.println(element);
}
system.out.println("===================================");
list<serviceinstance> instances = discoveryclient.getinstances("cloud-payment-service");
for (serviceinstance element : instances) {
system.out.println(element.getserviceid()+"\t"+element.gethost()+"\t"+element.getport()+"\t"+element.geturi());
}
return instances.get(0).getserviceid()+":"+instances.get(0).getport();
}
负载均衡算法:rest接口第几次请求数 % 服务器集群总数量 = 实际调用服务器位置下标 ,每次服务重启动后rest接口计数从1开始
2.4 负载均衡算法原理
算法切换
@configuration // 标记为配置类
@loadbalancerclient(value = "cloud-payment-service", configuration = resttemplateconfig.class) // 使用负载均衡器客户端注解,指定服务名称和配置类
public class resttemplateconfig {
@bean // 定义一个bean
@loadbalanced // 使用@loadbalanced注解赋予resttemplate负载均衡的能力
public resttemplate resttemplate() {
return new resttemplate(); // 返回一个新的resttemplate实例
}
@bean // 定义一个bean
reactorloadbalancer<serviceinstance> randomloadbalancer(environment environment, // 注入环境变量
loadbalancerclientfactory loadbalancerclientfactory) { // 注入负载均衡器客户端工厂
string name = environment.getproperty(loadbalancerclientfactory.property_name); // 获取负载均衡器的名称
// 创建并返回一个随机负载均衡器实例
return new randomloadbalancer(loadbalancerclientfactory.getlazyprovider(name, serviceinstancelistsupplier.class), name);
}
}
发表评论