
负载均衡的概念
1.1什么是负载均衡
Load Balancing,即负载均衡,是一种计算机技术,用来在多个计算机(计算机集群)、网络连接、CPU、磁盘驱动器或其他资源中分配负载,以达到最优化资源使用、最大化吞吐率、最小化响应时间,同时避免过载的目的
简单来说:负载均衡(Load Balance),即是将负载(工作任务、访问请求)进行平衡、分摊到多个操作单元(服务器、组件)上进行指向。是解决高性能、单点故障(高可用)、扩展性(水平伸缩)的终极解决方案
1.2为什么需要负载均衡
为了提升网站的服务能力,很多网站都采用了集群部署。就像电影院有很多个入口一样,这时候就需要一个协调者,来均衡的分配这些用户请求,可以让用户均匀的分派到不同的服务器上
1.3负载均衡分类
我们先回顾一下OSI七层模型:OSI是一个开放性的通信系统互联参考模型,他是一个定义的非常好的协议规范。OSI模型有7层结构,每层都可以有几个子层。OSI的七层从上到下分别是:
7.应用层
6.表示层
5.会话层
4.传输层
3.网络层
2.数据链路层
1.物理层
在这七层模型中,高层次都是依赖于低层次的。层次越高,使用起来越方便。其中高层(7,6,5,4)定义来应用程序的功能,下面3层(3,2,1)主要面向通过网络的端到端的数据流
计算机网络相关的概念:
TELNET、HTTP、FTP、NFS、SMTP、DNS等属于第七层应用层的概念
TCP、UDP、SPX等属于第四次传输层的概念
IP、IPX等属于第三层网络层的概念
ATM、FDDI等属于第二层数据链路层的概念
我们可以很明确的一点是,负载均衡是要在网络中传输做文章的。而要在网络传输过程中,那么这7层就势必绕不开
所以,根据负载均衡技术实现在OSI七层模型的不同层次,是可以给负载均衡分类的。
常见的实现方式中,主要可以在应用层、传输层、网络层和数据传输层做文章。所以,工作在应用层的负载均衡,我们通常称之为七层负载均衡,工作在传输层的我们称之为4层负载均衡
二层负载均衡
一般是用虚拟mac地址方式。负载均衡服务器对外提供一个VIP(虚IP),集群中不同的机器采用相同IP地址,但是机器的MAC地址不一样。当负载均衡服务器接收到请求之后,通过改写报文的目标MAC地址的方式将请求转发到目标机器实现负载均衡
三层负载均衡
一般是用虚拟IP地址方式。和二层负载均衡类似,负载均衡服务器对外依然提供一个VIP(虚IP),但是集群中不同的机器采用不同的IP地址。当负载均衡服务器接收请求之后,根据不同的负载均衡算法,通过IP将请求转发至不同的真实服务器。
四层负载均衡
用虚拟ip+port 方式。四层负载均衡工作在OSI七层模型的传输层,由于在传输层,只有TCP/UDP协议,这两种协议中除了包含源IP、目标IP以外,还包含源端口号及目的端口号。四层负载均衡服务器在接收到客户端请求后,通过修改数据包的地址信息(IP+端口号)将流量转发到应用服务器。
七层负载均衡
用虚拟url或主机名方式。七层负载均衡工作在OSI七层模型的应用层,应用层协议较多,常用http、radius、dns等。七层负载就可以基于这些协议来负载。这些应用层协议中会包含很多有意义的内容。比如同一个web服务器的负载均衡,除来根据IP + 端口号 进行负载外,还可以根据七层的URL、浏览器类别、语言来决定是否进行负载均衡。
因为负载均衡器通常称为四层交换机 或七层交换机。这里针对四层 和七层两者区别再深入说一下:
技术原理区别
四层负载均衡,主要通过报文中的目标地址和端口,再假设负载均衡设备的服务器选择方式,决定最终选择的内部服务器。
TCP的连接建立,即三次握手是客户端和服务端直接建立的,负载均衡设备只是起到一个类似路由器的转发动作。
七层负载均衡:主要通过报文中的真正有意义的应用层内容,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。
以常见的 TCP 为例,负载均衡设备如果要根据真正的应用层内容再选择服务服务器,只能先代理最终的服务器和客户端建立连接(三次握手)后,才可能接收到客户端发送的真正应用层内容的报文,然后再根据报文中的特定自带,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。负载均衡设在这种情况下,更类似于一个代理服务器 。负载均衡和前端的客户端以及后端的服务器会分别建立 TCP 连接。所以从这个技术原理上来看,七层负载均衡明显对负载均衡设备的要求更高,处理七层的能力也必然会低于四层模式的部署方式。
应用场景区别
七层因为可以代理任何修改和处理用户的请求,所以可以使整个应用更加智能化和安全,代价就是设计和配置会更加复杂。所以是否有必要使用七层负载是一个需要权衡的问题。
现在的七层负载协议,主要还是着重于应用HTTP协议,所以其应用范围主要是众多的网站或者内部信息管理平台等基于B/S开发的系统。四层负载均衡则对应其他TCP应用。
1.4负载均衡工具
Nginx、LVS、HAProxy是目前使用最广泛的三种负载均衡软件
LVS:主要用来做四层负载均衡
LVS(Linux Virtual Server),也就是 Linux 虚拟服务器,是一个由 章文颂博士 发起的自由软件项目,使用 LVS 技术要达到的目标是:通过LVS提供的负载均衡技术和Linux操作系统实现一个高性能、高可用的服务器集群架构,它具有良好的可靠性、可扩展性和可操作性。从而以低廉的成本实现最优的服务性能。
Nginx:主要用来做七层负载均衡
Nginx,是一个网页服务器,它能发现代理HTTP、HTTPS、SMTP、POP3、IMAP的协议链接,以及一个负载均衡器和一个HTTP缓存。
Nginx现在的负载均衡既支持四层(ngx_stream_core_module模块)、又支持七层(ngx_http_upstream_module模块),但由于LVS在四层负载均衡方面做得知名度实在是太高了,所以Nginx的四层负载均衡用的人不怎么多,网上也很少会有说用Nginx来做四层负载均衡的。
HAProxy:主要用来做七层负载均衡
HAPorxy,是一个使用 C 语言编写的自由开源软件,其提供高可用性、负载均衡,以及基于TCP和HTTP的应用程序代理。
1.5负载均衡算法
负载均衡算法可以分为两类:静态负载均衡算法和动态负载均衡算法。
静态负载均衡算法包括:轮询、比率、优先权
- 轮询,按顺序执行
- 比率:给每个服务器分配一个加权值比率
- 优先权:给所有服务器分组,给每个组定义优先权。
动态负载均衡算法包括:最少连接数、最快响应速度、观察方法、预测方法、动态性能分配、动态服务器补充、服务质量、服务类型、规则模式
- 少的连接方式(Least Connection):传递新的连接给那些进行最少连接处理的服务器。当其中某个服务器发生第二层到第七层的故障,BIG-IP 就把其从服务器队列中拿出,不参加下一次的用户请求的分配,直到其恢复正常。
- 最快模式(Fastest):传递连接给那些响应最快的服务器。当其中某个服务器发生第二层到第七层的故障,BIG-IP 就把其从服务器队列中拿出,不参加下一次的用户请求分配,直到其恢复正常。
- 观察模式(Observed):连接数目和响应时间以这两项的最佳平衡为依据为新的请求选择服务器。当其中某个服务器发生第二层到第七层的故障,BIG-IP 就把其从服务器队列中拿出,不参加下一次的用户请求分配,直到其恢复正常。
- 预测模式(Predictive):BIG-IP 利用收集到的服务器当前的性能指标,进行预测分析,选择一台服务器在下一个时间片内,其性能将达到最佳的服务器响应用户的请求。(被BIG-IP进行检测)。
- 动态性能分配(Dynamic Ratio-APM):BIG-IP 收集到的应用程序和应用服务器的各项性能参数,动态调整流量分配。
- 动态服务器补充(Dynamic Server Act.):当主服务器群中因故障导致数量减少时,动态地架构备份服务器补充至主服务器群。
- 服务质量(QoS):按不同的优先级对数据流进行分配。
- 服务类型(ToS):按不同的服务类型(在Type of Field 中标识)负载均衡对数据流进行分配。
- 规则模式:针对不同的数据流设置导向规则,用户可自行。
以上,就是目前实现负载均衡的主流算法,不同的负载均衡服务器会选择不同的算法。
1.6软件负载均衡和硬件负载均衡比较

硬件负载均衡解决方案是直接在服务器和外部网络间安装负载均衡设备,这种设备我们通常称之为负载均衡器,由专门的设备完成网络请求转发的任务,独立于操作系统,整体性能高,负载均衡策略多样化,流量管理智能化。
Nginx负载均衡
2.1Nginx负载均衡介绍
严格来说,Nginx仅仅是作为Nginx Proxy反向代理使用的,因为这个反向代理功能表现的效果是负载均衡的效果。
有一点需要注意,在使用Nginx作为其层负载均衡器时,如果Nginx上有设置proxy_cache,那么如果被访问的资源已经被缓存过,Nginx就不会再将请求转发给节点,而是直接返回缓存资源,也就是说,Nginx在配置缓存的情况下是有可能不会触发调度的
2.2Nginx负载均衡组建模块
实现Nginx负载均衡的组件主要有两个:
ngx_http_upstream_module
负载均衡模块,可以实现网站的负载均衡功能及节点的健康检查
ngx_http_proxy_module
proxy 代理模块,用于把请求转发给服务器节点或 upstream 服务器池
upstream模块介绍
1.upstream模块运行Nginx定义一组或多组节点服务器组,使用时可以通过proxy_pass代理方式把网站的请求发送到事先定义好的对应的 upstream 组的名字上,具体写法为:
proxy_pass http://server_pools
其中server_pools就是一个upstream 节点服务器组名字。
2.upstream配置案例
示例1:基本的upstream配置案例
upstream server_pools {# upstream是关键字必须有,后面的server_pools是upstream集群组的名字,可自定义名称,调用时就用这个名字。server 192.168.1.251:80 weight=5;server 192.168.1.252:80 weight=10;server 192.168.1.256:80 weight=15;# server关键字是固定的,后面可以接域名或IP。如果不指定端口,默认是80端口。weight代表权重,数值越大被分配的请求越多。}
示例2:较完整的upstream配置案例:
upstream blog_pools {server 192.168.0.223; #这行标签和下行是等价的server 192.168.0.224:80 weight=1 max_fails=1 fail_timeout=10s; #这行标签和上一行是等价的,此行多余的部分就是默认配置,不写也可以。server 192.168.0.225:80 weight=1 max_fails=2 fail_timeout=20s backup;# server最后面可以加很多参数,具体参数作用看下文的表格}
3.upstream模块参数
- server :负载后面的 RS 配置,可以是ip或者域名;
- weight :请求服务器的权重,默认值为1,越大表示接受的请求比例越大;
- max_failsnginx :尝试连接后端主机失败的次数,默认为1。这个数值需要配合 proxy_next_upstream、fastcgi_next_upstream、memcached_next_upstream 这三个参数来使用的。当 nginx 接收后端服务器返回这三个定义的状态码时,会将这个请求转发给正常工作的后端服务器,例如404、502、503;
- fail_timeout :在 max_fails 定义的失败次数后,距离下次检查的时间间隔,默认为10s
- backup :热备配置,标志这台服务器作为备份服务器,若主服务器全部宕机,就会向它转发请求。backup可以被用来做到sorry server的效果,也就是在后端服务器挂了的时候给个“对不起,网站暂时无法访问”之类的页面,用来提示用户。相比于将特定http status code的页面配置为类似效果的做法,这种做法的优势在于不会出现很长时间的超时等待,而是立马返回错误提示,用户体验会更好一些;
- down :表示当前server暂时不参与负载均衡,也就是将server标记为不可用状态,可配合 ip_hash 使用,实现灰度发布的效果;
- max_conns :在1.11.5 版本后新增的参数,指连接某后端服务器时最大并发活动连接数。
upstream web_pools {server linux.example.com weight=5;server 127.0.0.1:8080 max_fail=5 fail_timeout=10s;# 当5次连续检查失败后,间隔10s后重新检测。server linux.example.com:8080 backup;# 指定备份服务器。作用:等上面服务器全部不可访问时就向它转发请求。}
http_proxy_module模块(1)proxy_pass 指令介绍
proxy_pass 指令属于 ngx_http_proxy_module 模块,此模块可以将请求转发到另一台服务器。在实际的反向代理工作中,会通过 location 功能匹配指定的 URL,然后把接收到的符合匹配 URL 的请求通过 proxy_pass 抛给定义好的 upstream 节点池。
(2)proxy_pass 的使用案例location /web/ {proxy_pass http://127.0.0.1/abc/;}
将匹配URL为web的请求抛给http://127.0.0.1/abc/
2.3Nginx负载均衡调度算法
rr轮询(默认的模式)
默认的调度算法,按照客户端请求逐一分配到不同的后端服务器,宕机的服务器会自动从节点服务器池中剔除。
upstream server_pools {server 192.168.1.251;server 192.168.1.252;}...location / {proxy_pass http://server_pools;}
注意:对于服务器 性能不同 的集群,该算法容易引发 资源分配不合理 等问题。
wrr加权轮询(weight)
在rr轮询算法的基础上加上权重,权重和用户访问成正比,权重值越大,被转发的请求也就越多。
upstream web_pools {server linux.example.com weight=5;server 127.0.0.1:8080 max_fail=5 fail_timeout=10s;# 当5次连续检查失败后,间隔10s后重新检测。server linux.example.com:8080 backup;# 指定备份服务器。作用:等上面服务器全部不可访问时就向它转发请求。}
加权轮询应用于服务器性能不等的集群中,使资源分配更加合理化。
ip_hash(会话保持)
每个请求按访问IP 的 hash 结果分配,每个访客固定访问一个后端服务器,可解决 session 不共享的问题。然而由于是非一致性Hash算法,所以一旦节点数量发生变化,所有的分配映射关系就都会发生改变,在节点配置不稳定的情况下会无法达到预期的效果。
upstream server_pools {ip_hash;server 192.168.1.251;server 192.168.1.252;}
Session 不共享是说,假设用户已经登陆过,此时发出的请求被分配到了A服务器,但A服务器突然宕机,用户的请求则会被转发到B服务器,但由于Session不共享,B无法直接读取用户的登陆信息来继续执行其他操作。
url_hash(web缓存节点)
根据访问URL的hash结果来分配请求,让每个URL定向到同一个后端服务器。所以它非常适合在节点服务器为缓存服务器的情况下使用,能够大大地提供缓存命中率。然而由于是非一致性Hash算法,所以一旦节点数量发生变化,所有的分配映射关系就都会发生改变,在节点配置不稳定的情况下会无法达到预期的效果。
upstream server_pools {hash $request_uri;hash_method crc32;server 192.168.1.251;server 192.168.1.252;}
Nginx 在1.7.2 版本之前并不支持hash算法,如果需要在旧版中使用这种算法,就需要安装第三方的hash模块。配置时只需要在 upstream 配置中增加两行 hash $request_uri 、 hash_method crc32 。
fair(动态调度算法)
根据后端节点服务器的响应时间来分配请求,响应时间短的优先分配。
upstream server_pools {server 192.168.1.251;server 192.168.1.252;fair;}
Nginx 本身并不支持fair算法,如果需要使用,就需要安装第三方的upstream_fair 模块。
least_conn(动态调度算法)
根据后端节点服务器的连接数情况来分配请求,连接数少的会被优先分配。
least_conn 可以被用于大量长连接的场景(比如游戏服务器),它可以帮助节点服务器均分连接,使负载尽可能地保持相同。
least_conn 算法很简单,它会先遍历一遍所有的节点,比较它们的连接数,然后选取值最小的哪一个节点。如果有多个节点的连接数都是最小的,那么就对它们采用加权轮询算法。可以结合 weight 权重值使用。
upstream balabala {least_conn;server 192.168.1.251;server 192.168.1.252;}
consistent_hash
consistent_hash 是一个基于一致性 Hash 算法产生的静态调度算法,它是 ip_hash 和 url_hash 的升级版。
consistent_hash 同样会把每个请求按照客户端的IP、请求的URL的Hash结果(参数可选)来分配节点,使得同一个Hash值的请求能够始终分配到同一个节点上,它的独特之处在于,一致性Hash算法为它提供了故障前和一致性保持的效果。也就是说,即使在使用过程中某一个节点宕机了,其他Hash值和对应的节点也还是不会受影响,然后可以保持原来的映射关系;而这一个宕机的节点对应的那些Hash值,会被映射到环上的下一个节点上,达到故障迁移的效果。
配置时和url_hash类似,只需要在upstream配置中加一行consistent_hash $request_uri;即可。同样,这个参数也是可以替换为其他内容的。
upstream balabala {consistent_hash $request_uri;server 192.168.1.251;server 192.168.1.252;}
2.3 Nginx负载均衡配置实例
实现效果
在浏览器上输入地址http://www.test.com,实现负载均衡效果(可平均访问到两台服务器)
准备工作
(1) 准备3台nginx服务器,如下
主机名IP地址说明web01192.168.1.251Nginx web01服务器web02192.168.1.252Nginx web02服务器lb192.168.1.253Nginx 负载均衡服务器
(2) 三台服务器均安装Nginx
Nginx的安装这里就不再说了,网上很多参考。
(3) 配置用于测试的Web服务器
分别在web01 和 web02 进行配置
[root@web01 nginx]# cat conf/nginx.confworker_processes 1;events {worker_connections 1024;}http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;server {listen 80;server_name localhost;location / {root html/www;index index.html index.htm;}access_log logs/access_www.log main;}}
创建测试文件数据
[root@web01 ~]# cd /usr/local/nginx/html/[root@web01 html]# mkdir www[root@web01 www]# echo "`hostname` www" > index.html
查看创建的文件内容:
[root@web01 www]# cat index.htmlweb01 www
之后启动nginx服务。
(4) 配Nginx负载均衡服务器
[root@lb01 nginx]# cat conf/nginx.confworker_processes 1;events {worker_connections 1024;}http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;upstream www_server_pools { #这里定义Web服务器池,包含了251,252两个Web节点server 192.168.1.251:80 weight=1;server 192.168.1.252:80 weight=1;}server { #这里定义代理的负载均衡域名虚拟主机listen 80;server_name www.test.com;location / {proxy_pass http://www_server_pools; #访问www.test.com,请求发送给www_server_pools里面的节点}}}
(5) 域名解析由于不是真实环境,域名使用www.test.com用作测试,所以www.test.com 的解析只能在hosts文件设置。
mac系统:
sudo vi /etc/hosts
windows系统:
C:\Windows\System32\drivers\etc\hosts
在末尾添加:192.168.1.253 www.test.com
测试验证
打开浏览器访问www.test.com,不断刷新会发现所有请求被负载均衡服务器(192.168.1.253)均分配到web01(192.168.1.251)和web02(192.168.1.252)上,实现了负载均衡的效果。
