负载均衡分为四层负载均衡与七层负载均衡
所谓四层负载均衡就是指在OSI参考模型中的传输层,主要是基于ip + port方式的负载均衡
实现四层负载均衡方式:
硬件:F5,BIG-IP,EADWARE
软件:lvs,nginx,hayproxy
所谓七层负载均衡指的是OSI参考模型中的应用层,主要是基于URL或主机ip的负载均衡
实现七层负载均衡的方式:
软件:nginx,hayproxy等
四层负载均衡与七层负载均衡的区别:
- 四层负载均衡是将数据包在底层进行了分发,而七层这是数据包在顶层,所以四层负载均衡效率要比七层要高
- 四层负载均衡不能识别域名,而七层负载均衡可以识别域名
处理四层和七层以外还有其他层的方式,二层与三层负载。二层是数据链路层基于mac地址来实现负载均衡,三层是在网络层一般采用虚拟网络ip地址来实现负载均衡
实际采用模式= 四层(lvs)+七层(nginx)
一:七层proxy_upstream 负载均衡
来实现代理多个相同内容的服务器
环境:
name | ip | 作用 |
---|---|---|
ecs-node-0001 | 114.115.239.76 | nginx代理服务器 |
ecs-node-0002 | 114.115.213.208 | 模拟三台被代理的服务器 |
被代理主机:由于资源有限现用三个不同的端口来模拟三台服务器
[root@ecs-node-0002 ~]# vi /etc/nginx/nginx.conf
......
server {
listen 9001; #用三个不同的端口来模拟三台主机,切换到三台主机时效果一样
server_name localhost;
default_type text/html;
location / {
return 200 '<p>9001</p>'; #用户访问到看到的内容,为了让验证效果明显所以三个端口访问到的数字不同
}
}
server {
listen 9002;
server_name localhost;
default_type text/html;
location / {
return 200 "<p>9002</p>" ;
}
}
server {
listen 9003;
server_name localhost;
default_type text/html;
location / {
return 200 "<p>9003</p>";
}
}
代理主机:
[root@ecs-node-0001 ~]# vim /etc/nginx/nginx.conf
......#upstream是把相同服务器以组的方式放在一起进行访问
upstream backend {
server 114.115.213.208:9001;
server 114.115.213.208:9002;
server 114.115.213.208:9003;
}
server {
listen 8080; #暴露的端口
server_name localhost;
location / {
proxy_pass http://backend; #此处的名称要与upstream名称相同
} #proxy_pass反向代理,将将访问代理服务器时分发到upstream中
}
通过浏览器进行访问node1测试,代理服务器暴的是8080端口所以通过8080端口进行访问
如下所示通过刷新浏览器可查看到
二:代理服务器状态
代理服务器在负载调度负载调度中状态有以下几个:
down | 当前的server暂时不参与负载均衡 |
---|---|
backup | 预留备份服务器 |
max_fails | 允许最大请求失败次数 |
fails_timeout | 经过max_fails失败后服务暂停时间 |
max_conns | 限制最大链接数 |
1. down状态
name | ip | 作用 |
---|---|---|
ecs-node-0001 | 114.115.239.76 | nginx代理服务器 |
ecs-node-0002 | 114.115.213.208 | 模拟三台被代理的服务器 |
down状态将标记服务器为不可以状态,也不能参与负载均衡,一般对需要进行维护的服务器进行这个设置。
利用上面的环境将其中一个端口设置为down(模拟将一台主机设为 down)
[root@ecs-node-0001 ~]# vim /etc/nginx/nginx.conf
......
upstream backend {
server 114.115.213.208:9001 down ; #将其中一个端口设置为down(模拟将一台主机设为 down)
server 114.115.213.208:9002;
server 114.115.213.208:9003;
}
server {
listen 8080;
server_name localhost;
location / {
proxy_pass http://backend;
}
}
通过浏览器访问代理服务器的ip+监听端口测试发现9001已经不在出现
2. backup状态
name | ip | 作用 |
---|---|---|
ecs-node-0001 | 114.115.239.76 | nginx代理服务器 |
ecs-node-0002 | 114.115.213.208 | 模拟三台被代理的服务器 |
backup状态顾名思义就是当主节点正常时不进行服务当主节点有问题后设置为backup的服务器即顶上去
修改代理服务器配置文件:
[root@ecs-node-0001 ~]# vim /etc/nginx/nginx.conf
...#将9002端口设为backup(模拟9002主机设为backup)
upstream backend {
server 114.115.213.208:9001 down ; #down状态主机不参与负载均衡
server 114.115.213.208:9002 backup; #backup主机作为9003的备份
server 114.115.213.208:9003;
}
server {
listen 8080;
server_name localhost;
location / {
proxy_pass http://backend;
}
}
现在模拟9003端口不能访问所以将firewalld开启并放行9001-9003端口,再将9003端口关掉,最后看9002端口是否起效。
被代理主机开启9001-9003端口
[root@ecs-node-0002 ~]# firewall-cmd --permanent --add-port=9001/tcp #永久开启tcp的9001端口
success
[root@ecs-node-0002 ~]# firewall-cmd --permanent --add-port=9002/tcp
success
[root@ecs-node-0002 ~]# firewall-cmd --permanent --add-port=9003/tcp
success
[root@ecs-node-0002 ~]# firewall-cmd --reload #重新加载规则
这时通过代理服务器的8080端口可以访问到9003端口,且只能访问到9003
接下来将被代理服务器的9003端口关闭模拟9003主机不能使用看backup主机能否顶上去
在被代理服务器上将9003端口关闭并重新加载缓存
[root@ecs-node-0002 ~]# firewall-cmd --permanent --remove-port=9003/tcp
success
[root@ecs-node-0002 ~]# firewall-cmd --reload
success
再次通过浏览器访问代理服务器的8080端口,发现9003端口已经不能访问了而访问到的是9002
3.max_conns & fail_timeout
max_conns=’number’
用来设置代理服务器同时活动链接的最大数量,默认为0,表示不限制,改设置可以根据后端服务器性能来设置防止服务器被压垮
max_fail和fail_timeout
max_fail=’number’ :设置允许请求代理服务器失败的此时默认为1
fail_timeout= ‘time’ 设置经过max_fail后服务暂停时间默认10s
[root@ecs-node-0001 ~]# vim /etc/nginx/nginx.conf
...#将9002端口设为backup(模拟9002主机设为backup)
upstream backend {
server 114.115.213.208:9001 down ; #down状态主机不参与负载均衡
server 114.115.213.208:9002 backup; #backup主机作为9003的备份
server 114.115.213.208:9003 max_fail=3 fail_timeout=15; #设置最大链接失败3次,失败后链接时间15s
}
server {
listen 8080;
server_name localhost;
location / {
proxy_pass http://backend;
}
}
三:负载均衡策略
上面我们已经解决了基本的负载均衡将不同的请求分发到不同的主机,那么还有其他方式吗?当然有
nginx的upstream支持以下6中分配方式:
算法名称 | 说明 |
---|---|
轮循 | 默认方式 |
weight | 权重方式 |
ip_hash | 依据ip来分 |
least_conn | 依据最少链接方式 |
url_hash | 依据URL分配方式 |
fair | 依据响应时间 |
1.轮循
默认情况下就是轮循,轮循将收到的请求按顺序分发到后端服务器上,问题就是当后端服务器有好有坏时就会造成不平衡
[root@ecs-node-0001 ~]# vim /etc/nginx/nginx.conf
......
upstream backend {
server 114.115.213.208:9001;
server 114.115.213.208:9002;
server 114.115.213.208:9003;
}
server {
listen 8080;
server_name localhost;
location / {
proxy_pass http://backend;
}
}
2.weight加权(权重)
weight=number:用来设置服务器的权重,默认情况下为1,权重数值越大被分配到的几率就越大,这种情况可以根据后端服务器性能进行划分
[root@ecs-node-0001 ~]# vim /etc/nginx/nginx.conf
......
upstream backend {
server 114.115.213.208:9001 weight=10;
server 114.115.213.208:9002 weight=5;
server 114.115.213.208:9003 weight=2;
}
server {
listen 8080;
server_name localhost;
location / {
proxy_pass http://backend;
}
}
3.ip_hash(依据ip进行分配)
当对后端的多台动态应用服务器做负载均衡时,ijp. _hash指令能够将某个客户端P的请求通过哈希算法定位到同一台后端服务器上。这样,当来自某一个IP的用户在后端Web服务器A上登录后,在访问该站点的其他URL,能保证其访问的还是后端web服务器A。
语法 | ip_hash |
---|---|
默认值 | - |
位置 | upstream |
[root@ecs-node-0001 ~]# vim /etc/nginx/nginx.conf
......
upstream backend {
ip_hash ; #只需在up_stream这里加一个ip_hash即可
server 114.115.213.208:9001 ;
server 114.115.213.208:9002 ;
server 114.115.213.208:9003 ;
}
server {
listen 8080;
server_name localhost;
location / {
proxy_pass http://backend;
}
}
通过访问代理服务器的ip后发现怎么也不改变
需要额外多说一点的是使用ip. hash指令无法保证后端服务器的负载均衡,可能导致有些后端服务器接收到的请求多,有些后端服务器接收的请求少,而且设置后端服务器权重等方法将不起作用。
3.least_conn
最少连接,把请求转发给连接数较少的后端服务器。轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_ conn这种方式就可以达到更好的负载均衡效果。
[root@ecs-node-0001 ~]# vim /etc/nginx/nginx.conf
......
upstream backend {
least_conn ;
server 114.115.213.208:9001 ;
server 114.115.213.208:9002 ;
server 114.115.213.208:9003 ;
}
server {
listen 8080;
server_name localhost;
location / {
proxy_pass http://backend;
}
}
4.url_hash
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,要配合缓存命中来使用。同一个资源多次请求,可能会到达不同的服务器上,导致不必要的多次下载,缓存命中率不高,以及一些资源时间的浪费。而使用url_hash, 可以使得同一个url(也就是同一个资源请求)会到达同一台服务器,一旦缓存住了资源,再此收到求,就可以从缓存中读取。
[root@ecs-node-0001 ~]# vim /etc/nginx/nginx.conf
......
upstream backend {
hash $request-uri ;
server 114.115.213.208:9001 ;
server 114.115.213.208:9002 ;
server 114.115.213.208:9003 ;
}
server {
listen 8080;
server_name localhost;
location / {
proxy_pass http://backend;
}
}
http://114.115.239.76:8080/c
http://114.115.239.76:8080/b
http://114.115.239.76:8080/a
5.fair
fair采用的不是内建负载均衡使用的轮换的均衡算法,而是可以根据页面大小、加载时间长短智能的进行负载均衡。那么如何使用第三方模块的fair负载均衡策略。
fair是第三方库所以在使用前要先添加fair的库
[root@ecs-node-0001 ~]# vim /etc/nginx/nginx.conf
......
upstream backend {
fair ;
server 114.115.213.208:9001 ;
server 114.115.213.208:9002 ;
server 114.115.213.208:9003 ;
}
server {
listen 8080;
server_name localhost;
location / {
proxy_pass http://backend;
}
}
四:案例
1.对特定资源进行负载均衡
被代理服务器配置:
由于资源有限利用四个不同的端口模拟四台服务器
[root@ecs-node-0002 ~]# vim /etc/nginx/nginx.conf
......
server {
listen 9001;
server_name localhost;
default_type text/html;
location / {
return 200 '<p>9001</p>';
}
}
server {
listen 9002;
server_name localhost;
default_type text/html;
location / {
return 200 "<p>9002</p>" ;
}
}
server {
listen 9003;
server_name localhost;
default_type text/html;
location / {
return 200 "<p>9003</p>";
}
}
server {
listen 9004;
server_name localhost;
default_type text/html;
location / {
return 200 "<p>9004</p>";
}
}
代理服务器配置:
[root@ecs-node-0001 ~]# vim /etc/nginx/nginx.conf
......
upstream videobackend { #建立两个upstream来区分四台主机资源
server 114.115.213.208:9001 ;
server 114.115.213.208:9002 ;
}
upstream filebackend {
server 114.115.213.208:9003 ;
server 114.115.213.208:9004 ;
}
server {
listen 8080;
server_name localhost;
location /video { #访问video资源会分配到videobackend组内的后端服务器
proxy_pass http://videobackend;
}
location /file { #访问file资源会分配到filebackend组内的后端服务器
proxy_pass http://filebackend;
}
}
通过浏览器进行访问测试
http://114.115.239.76:8080/file
http://114.115.239.76:8080/video
2.对不同域名进行负载均衡
与上面的配置差不多
被代理服务器:
[root@ecs-node-0002 ~]# vim /etc/nginx/nginx.conf
......
server {
listen 9001;
server_name localhost;
default_type text/html;
location / {
return 200 '<p>9001</p>';
}
}
server {
listen 9002;
server_name localhost;
default_type text/html;
location / {
return 200 "<p>9002</p>" ;
}
}
server {
listen 9003;
server_name localhost;
default_type text/html;
location / {
return 200 "<p>9003</p>";
}
}
server {
listen 9004;
server_name localhost;
default_type text/html;
location / {
return 200 "<p>9004</p>";
}
}
代理服务器:
[root@ecs-node-0001 ~]# vim /etc/nginx/nginx.conf
......
upstream videobackend {
server 114.115.213.208:9001 ;
server 114.115.213.208:9002 ;
}
upstream filebackend {
server 114.115.213.208:9003 ;
server 114.115.213.208:9004 ;
}
server {
listen 8080;
server_name www.videobackend.com; #通过访问这个域名再到后端upstream的videobackend
location / {
proxy_pass http://videobackend;
}
}
server {
listen 8081;
server_name www.filebackend.com; #通过这个域名访问到后端服务器upstream的filebackend
location / {
proxy_pass http://filebackend;
}
}
由于这两个域名都是假域名所以要在代理服务器上的/etc/hosts文件做本地映射
127.0.0.1 www.filebackend.com
127.0.0.1 www.videobackend.com
测试:
由于是假域名所以在代理服务器本身用cul测试,这样就实现了域名的负载均衡
3.将url重写的负载均衡
将url重写的负载均衡其实就是客户端在访问服务器时原来服务器下某个文件已经不存在了(或改名称了),但还想把访问之前的那个名称来自动引到现在的文件
代理服务器配置:
[root@ecs-node-0001 ~]# vim /etc/nginx/nginx.conf
......
upstream backend {
server 114.115.213.208:9001 ;
server 114.115.213.208:9002 ;
}
server {
listen 8080;
server_name localhost;
location /file { #将访问http://ip/file重定向到http://server
rewrite ^(/file/.*) /server/$1 last;
}
location /server {
proxy_pass http://backend;
}
}
被代理服务器:
[root@ecs-node-0002 ~]# vim /etc/nginx/nginx.conf
......
server {
listen 9001;
server_name localhost;
default_type text/html;
location / {
return 200 '<p>9001</p>';
}
}
server {
listen 9002;
server_name localhost;
default_type text/html;
location / {
return 200 "<p>9002</p>" ;
}
}
测试:通过浏览器访问http://ip/file/'随便名称',发现还是到来server下