Nginx的负载均衡
简单理解负载均衡
把前端超高并发访问转发到后端多台服务器进行处理,解决单个节点的压力过大;造成web服务器响应很慢,容易导致服务器瘫痪;所以把用户的需求交给后端的多台服务器帮忙响应;
负载均衡的工作原理
负载均衡有两种方式:四层负载均衡和七层负载均衡;
四层的负载均衡
工作在七层协议的第四层,主要是传输层,负责的是转发;
接收到客户端的流量后,修改数据包的信息地址,主要是目的地址和端口和源地址,将流量转发到应用服务器上;
七层的负载均衡
工作主要是在第七层,负责的工作是代理;
- 首先:与客户建立一个完整的连接,并且分析客户的请求信息;
- 然后按照调度算法选择应用服务器处理;
- 最后,与应用服务器建立连接,让应用服务器处理真正的客户请求;
七层模型理解
- 应用层:http、tftp、ftp、nfs、smtp
- 表示层:Telnet、Rlogin、Snmp、Gopher
- 会话层:SMTP/DNS
- 传输层:TCP/UDP
- 网络层:IP/ICMP/ARP/RARP/AKP/UUCP
- 数据链路层:ppp
- 物理层
七层负载均衡实验
规划:
前端服务器:192.168.75.130
后端服务器1:192.168.75.131
后端服务器2:192.168.75.132
注意:如果物理机不太行,可以使用多ip的虚拟主机来实现;
前端服务器的配置
- upstream:主要是配置均衡池和调度方法;
- proxy_pass:主要是配置代理服务器ip或者服务器组的名字
- proxy_set_header:主要是配置转发给后端服务器的host和前端客户端真实ip;
实验:
配置前端服务器:130
#在http指令块下配置upstream,指定均衡组;
[root@node0 nginx]# vim conf/nginx.conf
http {
include mime.types;
default_type application/octet-stream;
upstream web { #这个就是配置web组
server 192.168.75.131;
server 192.168.75.132;
}
#在location指令块中配置proxy_pass
location / {
proxy_pass http://web;
proxy_next_upstream error http_404 http_502;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
#配置的参数解释:
proxy_next_upstream:这里代表当后端服务器返回404或者是502的时候,把信息转发到其他的后端服务器,不会给到客户看到;
proxy_set_header:代表把客户端的请求host转发给后端服务器
proxy_set_header:把客户端的ip转发给后端服务器,$http_x_real_ip这个变量可以获取原始用户的ip;
准备后端服务器的页面
[root@node1 nginx]# curl 192.168.75.131
这是131 默认的nginx的主页面
[root@node2-132 ~]# curl 192.168.75.132
这是132的服务器
首先测试一下:
发现访问130,然后会交由后端服务器131和132处理请求;
#访问一下前端服务器130
#这里很明显发现:访问130,会跳到后端131或者132服务器的页面;
[root@node2-132 ~]# curl 192.168.75.130
这是131 默认的nginx的主页面
[root@node2-132 ~]# curl 192.168.75.130
这是132的服务器
[root@node2-132 ~]# curl 192.168.75.130
这是131 默认的nginx的主页面
[root@node2-132 ~]# curl 192.168.75.130
这是132的服务器
均衡方式
设置轮询:
正常的,如果不设置权重,那么131会处理一次,132也会处理一次
就像正常访问一次;
决定权重的是在upstream 模块下的指定weight
#查看一下配置文件
[root@node0 ~]# vim /usr/local/nginx/conf/nginx.conf
......
http {
include mime.types;
default_type application/octet-stream;
upstream web {
server 192.168.75.131; #这里没有设置权重;
server 192.168.75.132;
}
.........
location / {
proxy_pass http://web;
proxy_next_upstream error http_404 http_502;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
#直接设置权重
[root@node0 ~]# vim /usr/local/nginx/conf/nginx.conf
......
upstream web {
server 192.168.75.131 weight=3;
server 192.168.75.132 weight=1;
}
[root@node0 ~]# nginx -s reload
#访问130查看效果-->结合while循环进行验证
#这里明显发现,131处理三次,然后132才处理一次;
[root@node0 ~]# while true;do curl 192.168.75.130;sleep 1; done
这是131 默认的nginx的主页面
这是131 默认的nginx的主页面
这是132的服务器
这是131 默认的nginx的主页面
这是131 默认的nginx的主页面
这是131 默认的nginx的主页面
这是132的服务器
这是131 默认的nginx的主页面
这是131 默认的nginx的主页面
这是131 默认的nginx的主页面
这是132的服务器
最大的连接次数:
如果说131或者132突然是崩溃了,那么会有什么情况?
#一直访问130,然后关闭131的nginx-->测试查看
[root@node0 ~]# while true;do curl 192.168.75.130;sleep 1; done
......
[root@node1 ~]# pkill nginx
#这里我们能够发现131关闭后,处理是一直由132处理的;
#一直访问130,但是把131的主页给移除
[root@node0 ~]# while true;do curl 192.168.75.130;sleep 1; done
......
这是131 默认的nginx的主页面
<html>
<head><title>403 Forbidden</title></head>
#移除131的主页文件
[root@node1 ~]# mv /usr/local/nginx/html/index.html /tmp
#这里也能发现,131没有查找到资源的话会报403的错误
这里的原理是:错误的连接是由proxy_next_upstream和fastcgi_next_upstream等模块决定的,在默认的情况下,nginx会自动将请求交给正常的服务器处理,
首先关闭了proxy_next_upstream这个模块关闭,查看效果
[root@node0 ~]# vim /usr/local/nginx/conf/nginx.conf
..........
include mime.types;
default_type application/octet-stream;
upstream web {
server 192.168.75.131 weight=3 max_fails=3 fail_timeout=9s;
server 192.168.75.132 weight=1;
}
location / {
proxy_pass http://web;
proxy_next_upstream off;
#proxy_next_upstream error http_404 http_502;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
#让131的nginx关闭
[root@node1 ~]# nginx -s stop
#重载配置文件,启动验证
[root@node0 ~]# while true;do curl 192.168.75.130;sleep 1; done
#验证的过程发现,它除了交给132处理,还会有报错到屏幕
.............
<body>
<h1>An error occurred.</h1>
<p>Sorry, the page you are looking for is currently unavailable.<br/>
Please try again later.</p>
<p>If you are the system administrator of this resource then you should check
the error log for details.</p>
<p><em>Faithfully yours, nginx.</em></p>
</body>
</html>
这是132的服务器
[root@node0 ~]# while true;do curl -I 192.168.75.130 2> /dev/null|grep HTTP/1.1 ;sleep 1; done
HTTP/1.1 200 OK
HTTP/1.1 502 Bad Gateway
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
#这里需要注意,超时时间是9s-->由fail_timeout来决定
#最多尝试三次,这是遵循轮询的规则,不是一个请求,连接三次,而是轮询三次,有三次的处理机会;
现在在把proxy_next_upstream这个选项打开,重新测试
#修改配置文件
[root@node0 ~]# vim /usr/local/nginx/conf/nginx.conf
........
http {
include mime.types;
default_type application/octet-stream;
upstream web {
server 192.168.75.131 weight=3 max_fails=3 fail_timeout=9s;
server 192.168.75.132 weight=1;
}
......
location / {
proxy_pass http://web;
#proxy_next_upstream off;
proxy_next_upstream error http_404 http_502;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
#重载配置文件查看结果
[root@node0 ~]# nginx -s reload
[root@node0 ~]# while true;do curl -I 192.168.75.130 2> /dev/null|grep HTTP/1.1 ;sleep 1; done
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
#原理:它的输出没有在屏幕上输出,是因为错误的响应码被proxy_next_upstream获取了,这次请求被转发到下一个正常的服务器期;
ip_hash
通过客户端ip进行hash,在通过hash值选择后端的服务器
#修改配置文件:
[root@node0 ~]# vim /usr/local/nginx/conf/nginx.conf
.......
http {
include mime.types;
default_type application/octet-stream;
upstream web {
ip_hash; #这里主要添加一个ip_hash,启用ip_hash功能
server 192.168.75.131 weight=3 max_fails=3 fail_timeout=9s;
server 192.168.75.132 weight=1;
}
............
location / {
proxy_pass http://web;
#proxy_next_upstream off;
proxy_next_upstream error http_404 http_502;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
[root@node0 ~]# nginx -s reload
#客户端访问前端ip
[root@node0 ~]# curl 192.168.75.130
这是131 默认的nginx的主页面
[root@node0 ~]# curl 192.168.75.130
这是131 默认的nginx的主页面
[root@node0 ~]# curl 192.168.75.130
#这里可以发现,132的nginx是正常的,但是访问的时候不会给到132处理
#我们把131关闭
[root@node1 ~]# nginx -s stop
#请求就会转到132服务器上
[root@node0 ~]# curl 192.168.75.130
这是132的服务器
[root@node0 ~]# curl 192.168.75.130
这是132的服务器
使用负载均衡的时候,会遇到会话保持的问题,意思就是当你访问同样的资源的时候,原来访问过的服务器会帮你保持这个会话,不用从其他服务器来调取资源;
实现会话保持的方法:
- ip_hash:根据哭护短的ip,将请求分配到不同的服务器上;
- cookie:服务器给客户端下发一个cookie,具有特定的cookie的请求会分配给它的发布者;
url_hash
通过客户请求的url进行hash,在通过hash值来选择后端的server;
#修改前端nginx的配置文件
[root@node0 ~]# vim /usr/local/nginx/conf/nginx.conf
............
http {
include mime.types;
default_type application/octet-stream;
upstream web {
hash $request_uri consistent;
server 192.168.75.131 ;
server 192.168.75.132 ;
}
[root@node0 ~]# nginx -s reload
#访问前端服务器130
[root@node0 ~]# curl 192.168.75.130
这是132的服务器
根据相应时间均衡
fail算法会根据后端节点的服务器的响应事假来分配请求,时间段的优先分配;
需要借助一个模块master.zip来进行实现;
#准备一下模块
[root@node0 src]# ls
nginx-1.17.10 nginx-1.17.10.tar.gz nginx-upstream-fair-master.zip
#解压模块
[root@node0 src]# unzip nginx-upstream-fair-master.zip
Archive: nginx-upstream-fair-master.zip
a18b4099fbd458111983200e098b6f0c8efed4bc
creating: nginx-upstream-fair-master/
inflating: nginx-upstream-fair-master/.gdbinit
inflating: nginx-upstream-fair-master/README
inflating: nginx-upstream-fair-master/config
inflating: nginx-upstream-fair-master/ngx_http_upstream_fair_module.c
#修改源码bug
[root@node0 src]# sed -i 's/default_port/no_port/g' nginx-upstream-fair-master/ngx_http_upstream_fair_module.c
#重新编写预编译nginx
[root@node0 nginx-1.17.10]# ./configure --prefix=/usr/local/nginx --add-module=../nginx-upstream-fair-master
#编译安装
[root@node0 nginx-1.17.10]# make && make install
#编辑完了再次编辑130-nginx的配置文件
[root@node0 ~]# nginx -s reload
.....
http {
include mime.types;
default_type application/octet-stream;
upstream web {
fair;
server 192.168.75.131 weight=1 max_fails=3 fail_timeout=9s;
server 192.168.75.132 ;
}
#重载配置文件
[root@node0 ~]# nginx -s reload
[root@node0 ~]# nginx -s reload
#访问前端ip-130
[root@node0 ~]# nginx -s reload
[root@node0 ~]# curl 192.168.75.130
这是132的服务器
[root@node0 ~]# cu
备用服务器配置
这里用132作为备用服务器,意思是只有主的服务器不能提供服务了,然后备用服务器才会顶上
#修改配置文件
[root@node0 ~]# !vim
vim /usr/local/nginx/conf/nginx.conf
..........
http {
include mime.types;
default_type application/octet-stream;
upstream web {
server 192.168.75.131 weight=1 max_fails=3 fail_timeout=9s;
server 192.168.75.132 backup;
}
#重载配置文件
[root@node0 ~]# nginx -s reload
#访问前端服务器
[root@node0 ~]# curl 192.168.75.130
这是131 默认的nginx的主页面
[root@node0 ~]# curl 192.168.75.130
这是131 默认的nginx的主页面
#把131的nginx关闭
[root@node0 ~]# curl 192.168.75.130
这是132的服务器
[root@node0 ~]#
四层负载均衡配置实验
使用到四层均衡配置的话,主要是stream和upstream的配置,但是ngiinx默认编译的时候没有编译进去,所以需要重新编译;
配置四层负载均衡
130是前端服务器
#重新编译nginx然后添加stream模块
[root@node0 ~]# cd /usr/local/src/nginx-1.17.10/
[root@node0 nginx-1.17.10]# ./configure --prefix=/usr/local/nginx --with-stream
[root@node0 nginx-1.17.10]# make && make install
#部署四层均衡需要在全局的模块中设置
[root@node0 ~]# vim /usr/local/nginx/conf/nginx.conf
.......
events {
worker_connections 1024;
}
stream {
upstream web {
server 192.168.75.131:80; #注意必须制定port端口
server 192.168.75.132:80;
}
server { #这个server要卸载stream上
listen 80;
proxy_connect_timeout 3s; #连接上游服务器超时间,超过则选择另外一个服务器
proxy_timeout 10s; #tcp连接闲置时间,超过则关闭
proxy_pass web; #均衡组
}
}
#重载验证
[root@node0 ~]# nginx -s reload
[root@node0 ~]# curl 192.168.75.130
端口转发实验
修改配置文件
[root@node0 ~]# vim /usr/local/nginx/conf/nginx.conf
........
events {
worker_connections 1024;
}
stream {
upstream web {
server 192.168.75.132:22; #转发发哦22端口
}
server {
listen 2222;
proxy_connect_timeout 3s;
proxy_timeout 10s;
proxy_pass web;
}
}
[root@node0 ~]# nginx -s reload
#验证-->神奇的发现,连接130会连接到132上面
[root@node3 ~]# ssh 192.168.75.130 -p 2222
The authenticity of host '[192.168.75.130]:2222 ([192.168.75.130]:2222)' can't be established.
ECDSA key fingerprint is SHA256:HopVZZv3jg6U4JiH16cbXzRJyxVhTpZ/R8DXKrtPDSI.
ECDSA key fingerprint is MD5:54:b3:96:c8:36:c4:74:8d:3f:f3:c2:fd:fb:46:56:7b.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[192.168.75.130]:2222' (ECDSA) to the list of known hosts.
root@192.168.75.130's password:
Last login: Sun Aug 1 07:15:05 2021 from 192.168.75.1
[root@node2-132 ~]#