Nginx负载均衡基本概述
Nginx负载均衡在生产环境中的其他名称:
负载 负载均衡 调度 load balance LB
公有云的其他名称:
SLB 阿里云负载均衡
QLB 青云负载均衡
CLB 腾讯负载均衡
ULB ucloud负载均衡
为什么需要使用负载均衡
负载均衡分类
四层负载均衡
所谓四层负载均衡指的是OSI七层模型中的传输层,传输层的Nginx已经能支持TCP/IP的控制,所以只需要对客户端的请求进行TCP/IP协议的包转发就可以实现负载均衡,那么它的好处是性能非常快,只需要底层进行应用处理,而不需要进行一些复杂的逻辑。
七层负载均衡
七层负载均衡它是在应用层,那么它可以完成很多应用方面的协议请求,比如我们说的HTTP应用的负载均衡,它可以实现HTTP信息的改写、头信息的改写、安全应用规则控制、URL匹配规则控制,以及转发、rewrite等等的规则,所以在应用层的服务里面,我们可以做的内容就更多,那么Nginx则是一个典型的七层负载均衡SLB。
四层负载均衡和七层负载均衡的区别
Nginx负载均衡配置场景
Nginx要实现负载均衡需要用到proxy_pass代理模块配置
Nginx负载均衡于Nginx代理不同的地方在于,Nginx代理一个location仅能代理一台后端主机,而Nginx负载均衡则是将客户端请求的代理转发至一组upstream虚拟服务池。
环境规划
角色 外网IP(NAT) 内网IP(LAN) 主机名
lb01 eth0:192.168.15.5 eth1:172.16.1.5 lb01
web01 eth0:192.16.15.7 eth1:172.16.1.7 web01
web02 eth0:192.16.15.8 eth1:172.16.1.8 web02
vim /etc/nginx/conf.d/web.nana.com.conf
server {
listen 80;
server_name web.nana.com;
root /web;
location / {
index index.html;
}
}
echo "web01..." > /web/index.html
systemctl restart nginx
vim /etc/nginx/conf.d/web.nana.com.conf
server {
listen 80;
server_name web.nana.com;
root /web;
location / {
index index.html;
}
}
echo "web02.." > /web/index.html
systemctl restart nginx
1. 创建参数配置文件
vim /etc/nginx/proxy_params
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_connect_timeout 30s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;
2. 创建Nginx负载均衡配置文件
vim /etc/nginx/conf.d/proxy_web.conf
upstream web {
# 创建虚拟服务池,定义虚拟服务池的名称为web
server 172.16.1.7:80; # 将服务器web01添加至定义好的虚拟服务池web
server 172.16.1.8:80; # 将服务器web02添加至定义好的虚拟服务池web
}
server {
listen 80;
server_name web.nana.com;
location / {
proxy_pass http://web; # Nginx代理指向是定义好的虚拟服务池web
# Nginx代理指向的是一台服务器,Nginx负载均衡,指向的是一个虚拟服务池。
include proxy_params;
}
}
systemctl restart nginx
测试Nginx负载均衡
在本机添加域名解析
C:\Windows\System32\drivers\etc
在hosts文件添加域名解析
192.168.15.5 web.nana.com
web.nana
,浏览器显示内容为web01...
;刷新页面,浏览器的显示内容为web02...
。tail -f /var/log/nginx/access.log
。不断地刷新页面,观察Nginx日志内容的变化。搭建Wordpress服务和WeCenter服务的负载均衡
关注我博客的小伙伴们,如果想搭建这个服务,需要先要搭建好LNMP架构服务。
如果有拆分LNMP架构的小伙伴们。需要确保数据库web01和web02是正常可以访问到数据库的数据的,NFS是正常挂载在Web01和Web02服务器上的。
lb01负载均衡服务器
1. 配置Nginx负载均衡
vim /etc/nginx/conf.d/proxy_nana.com.conf
upstream node {
# 定义一个虚拟服务池node
server 172.16.1.7:80;
server 172.16.1.8:80;
}
server {
listen 80;
server_name blog.nana.com; # 1. 通过不同的域名匹配不同的项目(浏览器-->代理服务器)
location / {
proxy_pass http://node; # 2. 代理服务器-->虚拟服务池node-->请求平均分发给web服务器
include proxy_params; # 导入常用参数配置文件(默认加上Host头信息[域名]),通过域名找到web服务器中对应的文件。
}
}
server {
listen 80;
server_name zh.nana.com; # 1. 通过不同的域名匹配不同的项目(浏览器-->代理服务器)
location / {
proxy_pass http://node; # 2. 代理服务器-->虚拟服务池node-->请求平均分发给web服务器
include proxy_params; # 导入常用参数配置文件(默认加上Host头信息[域名]),通过域名找到web服务器中对应的文件。
}
}
2. 重启Nginx
systemctl restart nginx
测试Nginx负载均衡特性
测试Nginx负载均衡
在本机添加域名解析
C:\Windows\System32\drivers\etc
在hosts文件添加域名解析
192.168.15.5 zh.nana.com blog.nana.com
zh.nana.com
或者blog.nana.com
,浏览器是可以正常访问到网站页面的。tail -f /var/log/nginx/access.log
。不断地刷新页面,观察Nginx日志内容的变化。测试Nginx高容灾
systemctl stop nginx
,刷新浏览器页面。我们发现浏览器还是可以正常访问到网站页面的。这也就说明,在虚拟服务池中,如果一台服务器的Nginx服务崩掉了,并不会影响整个架构的运行。后端连接请求超时问题
如果我们停止Web02服务器PHP服务systemctl stop php-fpm
,打开浏览器输入zh.nana.com
或者blog.nana.com
,会发现浏览器报错502。我们再刷新一次,会发现页面是可以正常访问的。不断地刷新页面,会发现502报错页面和正常的浏览器页面是会来回切换的。
vim /etc/nginx/proxy_params # Nginx负载均衡,参数配置文件
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
# 当Nginx虚拟服务池其中任意一台服务器返回错误码500,502,503,504等错误时,可以分配到下一台服务器程序继续处理,提高平台访问的成功率
proxy_http_version 1.1;
proxy_connect_timeout 30s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;
systemctl restart nginx
Nginx负载均衡调度算法
调度算法 概述
轮询 按时间顺序逐一分配到不同的后端服务器(默认的算法)
weight 加权轮询,weight值越大,分配到的访问几率越高
ip_hash 每个请求按访问IP的hash结果分配,这样来自同一个IP的固定访问一个后端服务器
url_hash 按照访问的URL的hash结果来分配请求,是每一个URL定向到同一个后端服务器
least_conn 最少链接数,哪个机器链接数最少就分发
- weight 加权轮询
vim /etc/nginx/conf.d/proxy_web.conf
upstream web {
server 172.16.1.7:80 weight=5;
server 172.16.1.8:80 weight=1;
# 配置权重,用户端请求访问5次web01主机后,再访问1次web02主机
}
...
- ip_hash 不能和加权轮询一起使用
ip_hash 能解决会话登陆问题,但是会造成负载不均衡,导致某一台主机流量过大,而另一台主机没什么流量。
vim /etc/nginx/conf.d/proxy_web.conf
upstream web {
ip_hash;
# 根据来源的IP自动分配主机,记录在内存里面。
# 如果我们第一次用浏览器访问web服务器,请求发送给了web01主机,那么请求会一直发送给web01主机。
# 除非web01主机down掉了,才会把请求发送给web02主机。如果web01主机恢复运行了,那么请求还是会发送给web01主机。
server 172.16.1.7:80;
server 172.16.1.8:80;
}
如果在后端Web主机配置一样的情况下,负载默认使用轮询的算法比较适用。
Nginx负载均衡后端状态
状态 概述
down 当前的server暂时不参与负载均衡
backup 预留的备份服务器
max_fails 允许请求失败的次数
fail_timeout 经过max_fials失败后,服务暂停时间
max_conns 限制最大的接收链接数
- down 一般用户停机维护时使用
vim /etc/nginx/conf.d/proxy_web.conf
upstream web {
server 172.16.1.7:80 down; # web01不参与负载均衡,跟注释web01效果一样
server 172.16.1.8:80;
}
- backup 当所有server不可用,才会启用backup
vim /etc/nginx/conf.d/proxy_web.conf
upstream web {
server 172.16.1.7:80 backup; # web02和web03都down机了,使用web01当作备用服务器
server 172.16.1.8:80;
server 172.16.1.9:80;
}
- max_conns 最大链接数
vim /etc/nginx/conf.d/proxy_web.conf
upstream web {
server 172.16.1.7:80 max_conns=3; # 如果同时来了10个连接,web01最大接受连接数为3个,剩下的全都给web02处理
server 172.16.1.8:80 ;
}
- fail_timeout 允许请求失败的次数
- max_conns 经过max_fails失败后,服务暂停的时间
这两个参数,一般用于检查后端服务器的健康情况,但是无法看到具体的指标
vim /etc/nginx/conf.d/proxy_web.conf
upstream web {
server 172.16.1.7:80 max_fails=2 fail_timeout=10s; # 最多允许客户端向服务端发送请求失败2次,超过2次,暂停服务10秒。
server 172.16.1.8:80 max_fails=2 fail_timeout=10s; # 最多允许客户端向服务端发送请求失败2次,超过2次,暂停服务10秒。
}
fail_timeout 、 max_conns 参数测试
我们可以先关闭web02的Nginx服务。不断刷新浏览器界面,观察lb01代理错误日志的记录的时间。
代理服务器的错误日志error.log,每隔10秒种记录一次日志,但是日志的记录内容并没有显示这两个参数配置的信息。
Nginx负载均衡健康检查
nginx_upstream_check_module
来检查后端服务的健康状态。我原本使用的是nginx1.20.0版本,但是当前第三方模块网址网址不支持没有nginx1.20.0版本的补丁!!!
所以这里我只能重新创建一台虚拟机,重新去官网下载了nginx-1.16.1版本来做实验。
这个实验的重点是需要了解,如何在不更改Nginx当前服务配置的情况下,给已经安装好的Nginx软件打补丁。
vim /etc/yum.repos.d/nginx16.repo
[nginx1.16]
name=nginx
baseurl=https://repo.huaweicloud.com/epel/7/x86_64/
enabled=1
gpgcheck=0
1. 安装需要的依赖软件
yum install -y gcc glibc gcc-c++ pcre-devel openssl-devel patch
2. 下载源件包
wget http://nginx.org/download/nginx-1.16.1.tar.gz
wget https://github.com/yaoweibin/nginx_upstream_check_module/archive/master.zip
3. 解压nginx源码包以及nginx_upstream_check_module第三方模块
tar -xf nginx-1.16.1.tar.gz
unzip master.zip
4. 进入nginx目录,打补丁(p1代表在nginx目录内,p0代表不在nginx目录内)
cd nginx-1.16.1/
patch -p1 <../nginx_upstream_check_module-master/check_1.16.1+.patch
# 把已经解压好的补丁包导入当前目录下
5. 在已有的负载均衡上增加健康检查的功能 # 添加健康检查的模块--add-module=/root/nginx_upstream_check_module-master
nginx-V # 查看当前nginx的默认参数
- 添加健康检查的新模块,并且进行编译前的系统检查
./configure --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-stream_ssl_preread_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-http_auth_request_module --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --add-module=/root/nginx_upstream_check_module-master --with-stream_ssl_module --with-google_perftools_module --with-debug --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic' --with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E'
6. 下载编译检查缺少的依赖关系软件
yum -y install libxslt-devel
yum -y install gd gd-devel
yum -y install perl-devel perl-ExtUtils-Embed
7. 开始编译并且安装
make && make install
8. 修改配置文件,添加健康检查模块
vim /etc/nginx/conf.d/proxy.conf
upstream web {
server 172.16.1.7:80 ;
server 172.16.1.8:80 ;
check interval=3000 rise=2 fall=3 timeout=1000 type=tcp; # 设置nginx健康检查模块显示在浏览器的内容
# interval:检查的间隔时间,单位为毫秒
# rise:请求2次正常,标记后端的状态为up
# fall:请求3次失败,标记后端状态为down
# timeout:超时时间,单位为毫秒
}
server {
listen 80;
server_name web.nana.com;
location / {
proxy_pass http://web;
include proxy_params;
}
location /upstream_check {
check_status; # 调用健康检查功能模块的网址web.nana.com/upstream_check
}
}
9. 重启nginx服务
nginx -t
systemctl restart nginx
Nginx负载均衡解决后端session共享概述
1. 在web01服务器安装phpmyadmin服务 # phpmyadmin服务是把session_id直接写入本地的浏览器缓存中的
cd /code
wget https://files.phpmyadmin.net/phpMyAdmin/5.1.0/phpMyAdmin-5.1.0-all-languages.zip
2. 解压phpmyadmin服务压缩包
unzip phpMyAdmin-5.1.0-all-languages.zip
3. 配置phpmyadmin配置文件服务连接远程的数据库
cp /code/phpMyAdmin-5.1.0-all-languages/config.sample.inc.php /code/phpMyAdmin-5.1.0-all-languages/config.inc.php # config.sample.inc.php这是一个模板文件,需要复制改名之后再进行修改
vim /code/phpMyAdmin-5.1.0-all-languages/config.inc.php
...
$cfg['Servers'][$i]['host'] = '172.16.1.51'; # 30行,修改连接数据库的ip地址
...
4. 配置php服务授权
chown -R www:www /var/lib/php/
ll /var/lib/php/
# total 0
# drwxrwx--- 2 www www 6 Aug 4 2019 session
# drwxrwx--- 2 www www 6 Aug 4 2019 wsdlcache
5. 修改Nginx服务的配置文件
vim /etc/nginx/conf.d/php.conf
server {
listen 80;
server_name php.nana.com;
root /code/phpMyAdmin-5.1.0-all-languages;
location / {
index index.php index.html;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
6. 重启Nginx服务
systemctl restart nginx
7. 在本机添加域名解析
C:\Windows\System32\drivers\etc
在hosts文件添加域名解析
192.168.15.7 php.nana.com
ll /var/lib/php/session/ 查看/var/lib/php/session/目录下系统默认生成的文件名===>session_id
# total 4
# -rw------- 1 www www 2521 May 12 23:33 sess_05557fe7dcb3e2da4288ce9ca53069cf
第二步. web02主机
1. 在web02服务器安装phpmyadmin服务 # phpmyadmin服务是把session_id直接写入本地的浏览器缓存中的
cd /code
wget https://files.phpmyadmin.net/phpMyAdmin/5.1.0/phpMyAdmin-5.1.0-all-languages.zip
2. 将web01配置好的phpmyadmin以及nginx的配置文件推送到web02主机上
scp -rp /code/phpMyAdmin-5.1.0-all-languages root@172.16.1.8:/code/ # 在web01上操作
scp /etc/nginx/conf.d/php.conf root@172.16.1.8:/etc/nginx/conf.d/ # 在web01上操作
3. 配置php服务授权
chown -R www:www /var/lib/php
4. 在web02上重启Nginx服务
systemctl restart nginx
第三步. lb01主机
1. 将web01和web02接入负载均衡
vim /etc/nginx/conf.d/proxy_php.conf
upstream php {
server 172.16.1.7:80;
server 172.16.1.8:80;
}
server {
listen 80;
server_name php.nana.com;
location / {
proxy_pass http://php;
include proxy_params;
}
}
2. 重启Nginx服务
nginx -t
systemctl restart nginx
3. 关闭Web01服务器的域名解析,在本机添加lb01服务器的域名解析
C:\Windows\System32\drivers\etc
在hosts文件添加域名解析
192.168.15.5 php.nana.com
测试
php.nana.com
对应的IP地址为lb01服务器192.168.15.5
。phpmyadmin
服务会出现如下的情况。造成无法登陆原因,就是因为会话无法共享问题。会话共享问题解决方法
vim /etc/yum.repos.d/redis.repo
[redis]
name=redis
baseurl=https://repo.huaweicloud.com/epel/7/x86_64/
enabled=1
gpgcheck=0
- 我这里使用的是db01数据库服务器当作redis缓存服务器使用了,生产环境中,我们一般会使用单独的redis缓存服务器
1. 安装redis内存数据库
yum -y install redis
2. 配置redis监听在172.16.1.0网段上
sed -i "/^bind/c bind 127.0.0.1 172.16.1.51" /etc/redis.conf # 修改配置redis配置文件,第61行
3.启动redis
systemctl restart redis
systemctl enable redis
- Web01服务器上做配置
1. 修改/etc/php.ini文件 # /etc/php.ini是配置php解析器的配置文件
vim /etc/php.ini
session.save_handler = redis # 第1231行,官方提示改成redis
session.save_path = "tcp://172.16.1.51:6379" # 第1264行,修改session写入文件的路径,redis默认监听在6379端口号上
# session.save_path = "tcp://172.16.1.51:6379?auth=123" # 如果redis存在密码,则使用该方式
session.auto_start = 1 # 第1294行,1表示启动
2. 注释/etc/php-fpm.d/www.conf里面的两条内容,否则session内容会一直写入本地/var/lib/session目录中
vim /etc/php-fpm.d/www.conf
;php_value[session.save_handler] = files # 第395行
;php_value[session.save_path] = /var/lib/php/session # 第396行
3. 重启php-fpm服务
systemctl restart php-fpm
4. 将web01服务器上配置好的文件覆盖到web02服务器上
scp /etc/php.ini root@172.16.1.8:/etc/php.ini
scp /etc/php-fpm.d/www.conf root@172.16.1.8:/etc/php-fpm.d/www
- web02服务器
1. 重启php-fpm服务
systemctl restart php-fpm
测试
- db01服务器
redis-cli # 进入redis客户端
127.0.0.1:6379> keys * # 查看服务端的session_id
1) "PHPREDIS_SESSION:0aec4cc7488d675c85d4395a4483a564" # 服务端的session_id和浏览器cookie记录session_id的一致
2) "PHPREDIS_SESSION:8a82ea11d562296eb1b9ce8bc766808a" # 以前登陆过的session_id值