Nginx七层负载均衡详解

您所在的位置:网站首页 nginx负载均衡实现原理图 Nginx七层负载均衡详解

Nginx七层负载均衡详解

2023-10-12 17:54| 来源: 网络整理| 查看: 265

Nginx负载均衡

Nginx负载均衡基本概述

Nginx负载均衡在生产环境中的其他名称: 负载 负载均衡 调度 load balance LB 公有云的其他名称: SLB 阿里云负载均衡 QLB 青云负载均衡 CLB 腾讯负载均衡 ULB ucloud负载均衡

为什么需要使用负载均衡

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

负载均衡分类

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

七层负载均衡 七层负载均衡它是在应用层,那么它可以完成很多应用方面的协议请求,比如我们说的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 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 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 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 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 测试 我们在浏览器用数据管理员的身份登陆phpmyadmin客户端,成功登陆之后,查看浏览器Cookie中缓存的session_id。 在这里插入图片描述查看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. 解压phpmyadmin服务压缩包 unzip phpMyAdmin-5.1.0-all-languages.zip 3. 将web01配置好的phpmyadmin以及nginx的配置文件推送到web02主机上 scp -rp /code/phpMyAdmin-5.1.0-all-languages [email protected]:/code/ # 在web01上操作 scp /etc/nginx/conf.d/php.conf [email protected]:/etc/nginx/conf.d/ # 在web01上操作 4. 配置php服务授权 chown -R www:www /var/lib/php 5. 在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/php/session # 第396行 3. 重启php-fpm服务 systemctl restart php-fpm 4. 将web01服务器上配置好的文件覆盖到web02服务器上 scp /etc/php.ini [email protected]:/etc/php.ini scp /etc/php-fpm.d/www.conf [email protected]:/etc/php-fpm.d/www.conf - web02服务器 1. 重启php-fpm服务 systemctl restart php-fpm

测试

配置好服务之后,我们是可以成功登陆的网站的。 在这里插入图片描述查看Redis服务器中记录的session_id - 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值 我们查看浏览器Cookie记录的session_id值,跟redis服务端记录的session_id进行对比,发现两个值是一样的,这就表示我们的登陆会话信息的session_id是写入Redis数据库中的,这就是通过redis内存数据共享解决了会话共享的问题。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3