前言
前面很多篇博客都有涉及到负载均衡,而负载均衡也并不是某一个框架的专利,从博主接触Java以来,使用的很多框架都自带了负载均衡的特点。今天,我们就来一探究竟,了解下负载均衡是什么,该怎么在项目中使用负载均衡。
什么是负载均衡
负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。
负载均衡(Load Balance)其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。
通俗点来讲,就好比你要去蹲坑,坑位有五六七八个,你去哪个坑都能解决你的问题,你可能这次去一号坑,下次二号坑......总之,可随机;也可以你自己喜欢哪个坑就常去哪个坑,这个叫权重;甚至你可以每次不重样,这就是轮训。比较常见的就这几张,实际上,负载均衡的策略远比我们想象的要多。
具体有哪些负载均衡策略,可以查看以下内容:
负载均衡有哪些常见策略?
负载均衡百度百科
其实吧,具体有哪些我不敢说不重要,你只要知道常用的几种就可以了,但涉及到不同的框架,可能存在负载均衡方式不一样的情况,需要在使用中慢慢体会。
为什么要使用负载均衡
我们可以假设一下,比如我们要在618去购买一个商品,这个商品只存在于一台服务器上,但是618大促价格很优惠,很多人都要去买,结果抢购的时候发现,由于访问量过载导致服务器卡死或者反应很慢,你的用户最后骂骂咧咧的卸载了你的应用,并发誓再也不用了,是不是血亏?
但是,如果你的商品服务器有多台,通过负载均衡策略将大流量分流到不同的服务器上,缓解了服务器压力,用户在购买的时候非常流畅,那么用户会不会更加喜欢使用你的应用呢?答案是肯定的。
我记得十几年前上学的时候,那时还是GPRS网络,网页QQ慢的勒,但当时并不觉得慢,只是觉得新奇,用现在的互联网思想来说,GPRS恐怕就是静止的网页,现在别说GPRS了,4G网很多人都不用了,更别提E网和3G网络了,卡卡的应用在当前快节奏的生活中完全无法生存。而这,就是我们要使用负载均衡的原因。
有哪些常用框架自带负载均衡
具体有哪些框架带负载均衡策略?这个其实是有很多的,我们可以查看上面博主推荐的两篇文章。此处,博主根据自己的使用情况,将用过的包含负载均衡功能的框架和大家做一个简单的分享,以便大家在使用的过程中能够明确目标,提高效率。
Nacos负载均衡
Nacos的负载均衡是在集群环境下,同时存在多个相同的服务B,此时服务A需要去调用服务B,因为B服务存在多个,那么具体调用哪个服务B呢?此时就用到了负载均衡,默认情况下是轮询的,不会厚此薄彼,但我们希望这种负载均衡可以优先本集群内调用,若本集群内的服务B不可用,再去调用其他集群的服务B。详情看下图:
我们总是希望集群A的实例优先调用集群A的其他实例,如果发生其他实例宕机的情况,再去调用其他集群的实例。这样的调用和负载均衡在上一篇中博主有详细讲解,此处不再赘述,传送门:Java开发 - 带你了解集群间的相互调用,你还在等什么?
但是吧,话说回来,这又和Nacos又有什么关系呢?实际上,Nacos只是起到了注册中心的作用,真正的负载均衡并不是Nacos,而是另有其人,我们继续往下面看。
RestTemplate负载均衡
Java开发 - 带你了解集群间的相互调用,你还在等什么?
在上面这篇博客中,博主分别是用了RestTemplate和Dubbo两个远程访问的RPC组件,其实还有一个RPC组件Feign,但基本都差不多,比如RestTemplate的负载均衡,我们在yml文件中添加了如下配置:
helloWorld:
ribbon:
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则
还需要将RestTemplate交给Bean:
package com.codingfire.helloservice.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
如此这般,你就可以直接使用RestTemplate了。
被注释的是随机访问其他服务,正在使用的是优先访问本集群的服务,本集群服务宕机才会访问其他集群的服务。这样就可以减轻服务器的压力,就好比一个工作,一个人做的时候累死了,给你加一个人一起做,一人一半,就轻松太多了。
但由于RestTemplate有如下缺点:
- 不能针对不同的HTTP请求方法(GET,POST,PUT,DELETE)进行定制化处理;
- 不支持异步HTTP请求
- 没有良好的API文档,导致开发者很难理解和使用它;
- 错误处理机制不够完善,很难捕获和处理请求过程中的异常。
基于其缺点和其他RPC的优势, RestTemplate现在已经很少人用了。但若是一些简单的项目,还是有使用价值的,毕竟使用起来是真的简单,可以不使用注册中心,但前提是你不用负载均衡,通过ip:port+路径的方式请求。总觉得这么做不太妥当,只能说,看项目规模和投入成本吧,这直接决定了你所用的技术。
Dubbo负载均衡
现在来说Dubbo,Dubbo的负载均衡其实和RestTemplate差不多,毕竟都是远程调用,不同点在于Dubbo必需要使用注册中心,否则无法发现服务,当然RestTemplate也是可以使用注册中心的,在这篇博客中我们有详细教程:Java开发 - 带你了解集群间的相互调用,你还在等什么?
Dubbo的负载均衡在这篇博客中也有详细教程,但是,博主查阅了不少资料,关于Dubbo怎么优先访问本集群的实例还没有解决,算是一个遗憾,关于Dubbo的详细介绍,博主后期准备单独出一篇内容来详细介绍,还请大家稍安勿躁。
Dubbo的负载均衡在配置中设置:
dubbo:
protocol:
port: -1 # 设置Dubbo服务调用的端口 设置-1能够实现动态自动设置合适端口,生成规则是从20880开始递增
name: dubbo # 设置端口名称,一般固定就叫dubbo
registry:
address: nacos://localhost:8848 # 配置当前Dubbo注册中心的类型和地址
consumer:
check: false # 设置为false表示当前项目启动时,不检查要调用的远程服务是否可用,避免报错
只要port设置-1,就可以动态设置合适的端口,你不用关心IP,这就是注册中心的妙用,他们都会被注册到注册中心,Dubbo可以根据其注册名找到对应服务。
其负载均衡算法博主推荐这篇文章给大家看看:
dubbo的负载均衡详解 讲解的倒是挺详细,大家只要知道怎么用就可以。
KeepAlived负载均衡
KeepAlived主要作用是IP飘移,博主曾在数据库使用,做IP的漂移,其好处是虚拟一个IP作为链接的对象,也可用于代理web服务器,不过相较于Nginx来说相对要复杂些,但并不是不可以。
一般来说,我们经常把使用了KeepAlived的框架称为高可用架构,具体怎么个高可用,推荐两篇博客给大家看看:
Keepalived 实现负载均衡
Keepalived负载均衡
关于KeepAlived的使用,此处暂不讲解,后续陆陆续续出吧,总有讲解完的一天,想想都是一个浩大的工程。
Nginx负载均衡
刚刚有提到Nginx代理,Nginx常被用来做web的代理服务器,或者是反向代理,关于web服务器的代理就是基于反向代理的,只不过代理的是多台服务器,属于是静态资源的集群,可见一下配置:
#upstream指令可以定义一组服务器
upstream targetserver{
server 192.168.0.121:8080;
server 192.168.0.121:8081;
}
server {
listen 8080;
server_name localhost;
location / {
proxy_pass http://targetserver;
}
}
Nginx提供了如下负载均衡策略:
名称 | 说明 | 特点 |
---|---|---|
轮询 | 默认方式 | |
weight | 权重方式 | 根据权重分发请求,权重大的分配到请求的概率大 |
ip_hash | 依据ip分配方式 | 根据客户端请求的IP地址计算hash值, 根据hash值来分发请求, 同一个IP发起的请求,会发转发到同一个服务器上 |
least_conn | 依据最少连接方式 | 哪个服务器当前处理的连接少,请求优先转发到这台服务器 |
url_hash | 依据url分配方式 | 根据客户端请求url的hash值,来分发请求, 同一个url请求,会发转发到同一个服务器上 |
fair | 依据响应时间方式 | 优先把请求分发给处理请求时间短的服务器 |
比如权重:
#upstream指令可以定义一组服务器
upstream targetserver{
server 192.168.0.121:8080 weight=10;
server 192.168.0.121:8081 weight=5;
}
详细的配置此处不再赘述,此处只做扫盲,请自行查找。
Mycat负载均衡
Mycat是啥应该都知道吧?如果你不知道是啥,那分库分表总该知道吧?没错Mtcat就是用于分库分表的框架。
所以,Haproxy+keepalived+mycat高可用负载均衡集群你了解多少?
在Haproxy的配置文件中有这么一段配置:
listen mycat
bind 0.0.0.0:3300
mode tcp
balance roundrobin
server mycat-120 192.168.0.120:8066 check port 8066 maxconn 300
server mycat-121 192.168.0.121:8066 check port 8066 maxconn 300
Haproxy监听mycat,并且做了负载均衡,其逻辑是,keepalived IP飘移并且监听Haproxy状态,Haproxy监听mycat,mycat连接数据库做分库分表。此处主要是做了数据库连接的负载均衡,详细的步骤博主暂时就不讲解了,大家可自行了解,博主也会在后续的博客中详细加讲解这种模式的使用。
Gateway负载均衡
Gateway也是具备一定的负载均衡能力的,Gateway的负载均衡规则是
通过服务注册中心的服务名/接口实现负载均衡的,实际上并没有什么明显的配置,如随机啊,轮询啊,权重啊这些。
如果你看了Nacos的负载均衡,并看了那篇推荐的博客,你会发现,在Nacos中,可以对集群的服务配置权重,虽然并不是直接通过Gateway来设置权重,只能说这也是种办法。
有些同学会讲,我在配置文件中通过URI设置lb不是负载均衡吗?是的!uri 的协议为 lb( load Balance ),表示启用 Gateway 的负载均衡功能。但这实际上并不是Gateway本身的能力,是以注册中心上微服务名为路径创建动态路由进行转发,从而实现的动态路由功能。本质上是Nacos(注册中心)的能力。见以下配置:
spring:
application:
name: gateway # 服务名称
cloud:
nacos:
server-addr: localhost:8848 # nacos地址
gateway:
routes: # 网关路由配置
- id: user-service # 路由id,自定义,只要唯一即可
# uri: http://127.0.0.1:8081 # 路由的目标地址
uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
- Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求
虽然说负载均衡是Nacos的能力,但由于配置在Gateway下,我们就当是Gateway的能力。
给大家推荐几篇网关的文章:
三、Gateway实现负载均衡
23.Gateway 动态路由,负载均衡
结语
你还知道哪些具备负载均衡能力的框架呢?可以和博主一起探讨一下,博主抛砖引玉,还望大家不吝赐教。本篇博客写完了,但博主的心却很沉重。虽然讲的比较浅,但是博主想的却很多,也看到了自己的很多不足之处,技术这条路从来都不是一蹴而就的,它是一门绝对不容出错的艺术,因为错了,就无法得到想要的结果。未来很远,还需要继续努力。