说到负载均衡,我想说它天生就是不公平的。为何这么说呢?请你想象这么一个场景,一块蛋糕切成5份,如今要将它分给A、B、C3我的,基于公平原则,咱们说每一个人正常能够分到5/3份,可是,5/3份很明显很差进行划分,诶碰巧这个时候A中午没有吃饭,能多吃几份,B、C肚子偏饱,1份便可,基于不公平原则,咱们分给A3份蛋糕,B、C个一份,这样按照必定策略将资源进行划分的方式,是一种均衡的策略。html
在web应用中,一个web应用(或者说某个服务)在生产环境中通常是集群部署,而后采用负载均衡硬件(F5)或者软件(nginx)将请求分发到不一样的服务主机中进行处理,很明显,这里的蛋糕就至关于咱们的web request,假设有5个request进来,基于必定的均衡策略,咱们可能会将其中的3个request交给A服务器去处理,B、C服务器各处理1个request。下面我画张图片简单说明这个模型:nginx
那么使用负载均衡有什么好处呢?首先优化资源利用率,最大化吞吐量,减小延迟,再者系统的伸缩性和可靠性也获得了相应的保障。web
负载均衡技术少不了相关的均衡策略,Nginx 中提供了 4 种均衡策略,咱们能够根据具体的业务场景选择合适的均衡策略。下面分别介绍这 4 中均衡策略:算法
一、基于轮询的均衡策略:后端
轮询嘛,就是说对进到nginx的request按照遍历的方式进行分发,若是request 1 分发到 Server A,那么request 2将被分发到 Server B,......以此循环类推bash
二、基于最少链接数的均衡策略:服务器
最少链接,也就是说nginx会判断后端集群服务器中哪一个Server当前的 Active Connection 数是最少的,那么对于每一个新进来的request,nginx将该request分发给对应的Server.并发
三、基于ip-hash的均衡策略:app
咱们都知道,每一个请求的客户端都有相应的ip地址,该均衡策略中,nginx将会根据相应的hash函数,对每一个请求的ip做为关键字,获得的hash值将会决定将请求分发给相应Server进行处理负载均衡
四、基于加权轮询的均衡策略:
加权轮询,很显然这个策略跟咱们开题引入的场景是同样的,nginx会给Server配置相应的权重,权重越大,接收的request数将会越多
上面的均衡策略其实都很是很好理解,可是若是想了解其实现原理,能够看源代码,可是小编就算了,我是看不懂C、C++的。
这个是Nginx默认的均衡算法,若是你不进行相关的配置,默认会执行该策略,配置以下:
http {
upstream myapp1 {
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}
server {
listen 80;
location / {
proxy_pass http://myapp1;
}
}
}
复制代码
能够看出,nginx负载均衡使用到的指令很少,其中比较重要的两个是upstream
和proxy_pass
,upstream
块定义一个后端小集群,里边配置相关的Server组成这个集群,同时upstream
为这个集群起个相应的名字,本实例叫myapp1
.proxy_pass
处于location
块中,表示对于全部符合/
的request,将会交给哪一个集群进行处理,本实例为http://myapp1
。
但又一点咱们须要注意,上面http://myapp1
中myapp1
必须是upstream
起的名字,对于协议是使用http
仍是https
,都无所谓,若是你的协议使用https
,则将http
直接改为https
便可。另外,若是你在upstream
中的server
指令中指定了协议名,那么在proxy_pass
指令中就不须要加上协议名称了。
nginx负载均衡使用反向代理实现,也就是咱们上面使用到的proxy_pass
指令,支持的协议不止是http
和https
,同时还支持FastCGI
、uwsgi
、SCGI
、memcached
、gRPC
,若是你须要使用除了http
、https
外的其余协议,咱们不能使用proxy_pass
指令了,应该转而使用相应的指令,如fastcgi_pass
、uwsgi_pass
、scgi_pass
、memcached_pass
、grpc_pass
。
该策略处理负载,小编认为仍是有缺陷的,不能防止某台Server出现负载太高的状况。由于若是有些请求执行时间过长,而系统的并发量却很是大,那么就可能致使某台Server出现request堆积,负载太高,snowslide is possible~
该策略主要使用了least_conn
指令,具体配置以下:
upstream myapp1 {
least_conn;
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}
复制代码
该策略仍是比较人性化的,能够按照机器的实际状况进行刚需分配。
固然了,若是咱们想实现这样一个功能,咱们想让对于相同客户端的请求每次都被分发到同一个Server进行处理,上面两种策略都是不作到。此策略可确保来自同一客户端的请求始终定向到同一服务器,但此服务器不可用时除外。相关配置以下:
upstream myapp1 {
ip_hash;
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}
复制代码
既然相同客户端的请求能被同一台Server进行处理,那么相同客户端的会话Session就能够实现持久化了。
基于加权轮询的策略就不须要过多讲解了,就是在轮询的基础上加上个权重信息
upstream myapp1 {
server srv1.example.com weight=3;
server srv2.example.com;
server srv3.example.com;
}
复制代码
这种策略适合Server机器处理能力有区别的状况。
一、健康检查
不只人须要体检,机器也是须要体检的,那么就当nginx就是那位体检医生吧!nginx健康检查是什么呢?当咱们一个request进来被分发到相应的Server进行处理后,nginx会检查该request执行是否超时,是否执行失败了等状况,而后作出相应的处理---好比说当nginx检查出Server A执行某request时报出502错误了,那么下次nginx负载均衡时就会在upstream
块中将Server A排除掉,不分发请求给到Server A了。
对于健康检查的功能,nginx提供了基本两个指令,即max_fails
和fail_timeout
,也就是说当nginx检查到某Server发生错误的request数达到max_fails
或者执行某request执行时间超过fail_timeout
了,若是发生超时了,nginx将开始使用实时请求优雅地探测Server,若是有响应,则认为对应的Server仍是活着的,没有毛病的。
二、更多配置
针对上面upstream
块中的server
指令,其格式为:server address [parameters];
,里边的parameters
能够有不少的参数类型,好比说指定某台Server不参与负载均衡等。具体配置详见官网连接,点击此处传送门。