Nginx七层负载均衡详解

Posted 我的紫霞辣辣

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nginx七层负载均衡详解相关的知识,希望对你有一定的参考价值。

nginx负载均衡

Nginx负载均衡基本概述

Nginx负载均衡在生产环境中的其他名称:	
负载		负载均衡		调度		load balance	  LB

公有云的其他名称:
SLB			阿里云负载均衡
QLB			青云负载均衡
CLB			腾讯负载均衡
ULB			ucloud负载均衡

为什么需要使用负载均衡

  • 当我们的Web服务器直接面向用户,往往要承载大量并发请求,单台服务器难以负荷,我使用多台Web服务器组成集群,前端使用Nginx负载均衡,将请求分散的打到我们后端服务器集群中,实现负载的分发。那么会大大提升系统的吞吐率、请求性能、高容灾。
    在这里插入图片描述
  • 往往我们接触的最多的就是SLB负载均衡,实现最多的也是SLB,那么SLB它的调度节点和服务节点通常是在一个地域里面。那么它在这个小的逻辑地域里面决定了它对部分服务的实时性、响应性是非常好的。
  • 所以说,当海量的用户请求过来以后,它同样是请求调度节点,调度节点将用户的请求转发给后端对应的服务节点。服务节点处理完请求后再转发给调度节点,调度节点最后响应给用户节点。这样也能实现一个均衡的作用,Nginx是一个典型的SLB。

负载均衡分类

  1. 四层负载均衡
    所谓四层负载均衡指的是OSI七层模型中的传输层,传输层的Nginx已经能支持TCP/IP的控制,所以只需要对客户端的请求进行TCP/IP协议的包转发就可以实现负载均衡,那么它的好处是性能非常快,只需要底层进行应用处理,而不需要进行一些复杂的逻辑。
    在这里插入图片描述

  2. 七层负载均衡
    七层负载均衡它是在应用层,那么它可以完成很多应用方面的协议请求,比如我们说的HTTP应用的负载均衡,它可以实现HTTP信息的改写、头信息的改写、安全应用规则控制、URL匹配规则控制,以及转发、rewrite等等的规则,所以在应用层的服务里面,我们可以做的内容就更多,那么Nginx则是一个典型的七层负载均衡SLB。
    在这里插入图片描述

四层负载均衡和七层负载均衡的区别

  • 四层负载均衡数据在底层就进行了分发,而七层负载均衡数据包则是在最顶层进行分发,由此可以看出,七层负载均衡效率没有四层负载均衡高。
  • 但是七层负载均衡更贴近于服务,如HTTP协议就是七层协议,我们可以用Nginx可以作会话保持,URL路径规则匹配,head头改写等等,这些都是四层负载均衡无法实现的。

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
  1. web01服务器配置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 "web01..." > /web/index.html
systemctl restart nginx
  1. web02服务器配置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. lb01服务器配置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...
  • 我们也可以同时打开web01和web02的终端,输入tail -f /var/log/nginx/access.log。不断地刷新页面,观察Nginx日志内容的变化。
  • 如果日志记录的内容是来回切换的,那么说明客户的请求是被 lb01代理服务器服务器分别发放给两台web服务器做处理。

搭建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,浏览器是可以正常访问到网站页面的。
  • 我们也可以同时打开web01和web02的终端,输入tail -f /var/log/nginx/access.log。不断地刷新页面,观察Nginx日志内容的变化。
  • 如果日志记录的内容是来回切换的,那么说明客户的请求是被lb01代理服务器分别发放给两台web服务器做处理。

测试Nginx高容灾

  • 我们直接停用Web01服务器的Nginx服务systemctl stop nginx,刷新浏览器页面。我们发现浏览器还是可以正常访问到网站页面的。这也就说明,在虚拟服务池中,如果一台服务器的Nginx服务崩掉了,并不会影响整个架构的运行。

后端连接请求超时问题

如果我们停止Web02服务器php服务systemctl stop php-fpm,打开浏览器输入zh.nana.com或者blog.nana.com,会发现浏览器报错502。我们再刷新一次,会发现页面是可以正常访问的。不断地刷新页面,会发现502报错页面和正常的浏览器页面是会来回切换的。

  • 如果后台服务连接超时,Nginx是本身有机制的,如果出现一个节点down掉的时候,Nginx会根据你具体负载均衡的设置,将请求转移到其他节点上。但是,如果后台服务连接没有down掉,但是返回错误异常了,如504、502、500等。这个时候我们需要在Nginx代理服务器上加一个负载均衡设置。
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

upstream虚拟服务池模块

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官方提供的模块中,没有对负载均衡后端节点的健康检查模块,但是可以使用第三方模块nginx_upstream_check_module来检查后端服务的健康状态。

我原本使用的是nginx1.20.0版本,但是当前第三方模块网址网址不支持没有nginx1.20.0版本的补丁!!!
所以这里我只能重新创建一台虚拟机,重新去官网下载了nginx-1.16.1版本来做实验。
这个实验的重点是需要了解,如何在不更改Nginx当前服务配置的情况下,给已经安装好的Nginx软件打补丁。

  • 配置nginx-1.16.1版本epel源
vim /etc/yum.repos.d/nginx16.repo
[nginx1.16]
name=nginx
baseurl=https://repo.huaweicloud.com/epel/7/x86_64/
enabled=1
gpgcheck=0
  • 添加Nginx健康检查模块
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
  • 测试
    浏览器输入域名web.nana.com/upstream_check,可以通过图形界面的形式,查看当前后端服务器(web01和web02)的状态。
    在这里插入图片描述

Nginx负载均衡解决后端session共享概述

模拟无法会话共享问题
在这里插入图片描述
第一步. web01主机

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	
  • 测试
  1. 我们在浏览器用数据管理员的身份登陆phpmyadmin客户端,成功登陆之后,查看浏览器Cookie中缓存的session_id。
    在这里插入图片描述
  2. 查看web01服务器中的session_id值,我们会发现是一样的。
ll /var/lib/php/session/				查看/var/lib/php/session/目录下系统默认生成的文件名===>session_id	
# total 4
# -rw------- 1 www www 2521 May 12 23:33 sess_05557fe7dcb3e2da4288ce9ca53069cf
  • 如果我们清除浏览器缓存之后,重新登陆phpmyadmin客户端,会发现浏览器和web01服务器中的session_id都会发生变化。

第二步. 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

测试

  • 我们配置好Web01和Web02主机后,添加负载均衡服务器lb01。可以通过cmd测试,确认域名php.nana.com对应的IP地址为lb01服务器192.168.15.5
  • 因为我们负载默认是采用轮询的方式进行请求的转发的,我们登陆phpmyadmin服务会出现如下的情况。造成无法登陆原因,就是因为会话无法共享问题。
  • 用户输入密码后,session_id登陆的标记,记录在web01服务器中;用户发起加载网站页面的第二次请求,负载会把登陆请求转发给web02服务器,但是web02服务器中并没有记录session_id的登陆的标记,这就导致了用户无法登陆的情况。
    在这里插入图片描述

会话共享问题解决方法

在这里插入图片描述
使用Redis解决会话登陆问题

  • 配置Redis的华为云epel源
vim /etc/yum.repos.d/redis.repo
[redis]
name=redis
baseurl=https://repo.huaweicloud.com/epel/7/x86_64/
enabled=1
gpgcheck=0
  • 配置Redis服务端
- 我这里使用的是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
  • PHP配置session连接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以上是关于Nginx七层负载均衡详解的主要内容,如果未能解决你的问题,请参考以下文章

Nginx四层负载均衡详解 #yyds干货盘点#

负载均衡详解

七层负载均衡 nginx

Nginx---负载均衡和缓存

nginx七层负载均衡

nginx七层负载均衡