👺1.nginx负载均衡介绍
1.1什么是负载均衡?
负载均衡是Load Balance 简称LB ,指的是将工作任务进行平滑,分摊到多个操作到多个单元上运行。
1.2为什么需要使用负载均衡?
当我们的web服务器直接面向用户,往往要承载大量并发请求,单台服务器难以负荷,我们使用多台web服务器组成集群,前端使用Nginx负载均衡,将请求分散的打到我们的后端服务器集群中,实现负载的分发。从而提升整体性能,以及系统的容灾能力
1.3负载均衡实现的方式
硬件:f5、
软件:
七层:Nginx Haproxy
四层:LVS ( Nginx 、Haproxy )
云厂商:
LB产品,它支持四层和七层?同时你只需要购买你需要的连接数即可?
云厂商负载均衡的名词:
SLB 阿里
CLB 腾讯
ULB ucloud
QLB 青云
👺2.nginx负载均衡场景
OSI七层模型封包解包过程
2.1 四层负载均衡 TCP 转发 LVS
所谓的四层负载均衡指的是osi七层模型中的传输层,四层仅需要对客户端的请求进行TCP/IP协议的包转发就可以实现负载均衡。四层负载均衡的性能极好,因为只需要底层进行转发的处理,而不能进行一些复杂的逻辑。
2.2 七层负载均衡 HTTP 代理
七层负载均衡它是在应用层,那么它可以完成很多应用方面的协议请求,比如我们说的http应用负载均衡,它可以实现
http头信息的改写(proxy_set_header )
,安全应用规则控制
,URI匹配规则控制
,及rewrite等功能
,所以在应用层里面可以做的内容比四层负载均衡要多。
2.3 四层负载均衡和七层负载均衡的区别
四层负载均衡数据包在底层就进程了分发
七层负载均衡数据包则是在最顶层进行分发。
--> 由此可以看出: 七层负载均衡效率没有四层负载均衡效率高。
但七层负载均衡更贴近与服务,(http协议就是七层协议)
我们可以用Nginx做URI路径规则匹配,Head改写。Rewirte,会话保持等,这些都是四层均衡负载无法实现的。
👺3.nginx负载均衡场景
Nginx要实现负载均衡需要用到proxy_pass
和upstream
两个模块
upstream
:定义多台服务器为一组虚拟机的资源池(名词)
proxy_pass
:实现反向代理----->代理到upstream定义的资源池名称。
Nginx upstream虚拟配置语法:
Syntax:
upstream name { ... }
Default: —
Context: http
#upstream实列
upstream backend {
server backend1.example.com weight=5;
server backend2.example.com:8080;
server unix:/tmp/backend3;
server backup1.example.com:8080 backup;
server backup2.example.com:8080 backup;
}
server {
location / {
proxy_pass http://backend;
}
}
网络规划
角色 | 外网IP(NAT) | 内网IP(LAN) | 主机名 |
---|---|---|---|
LB01 | eth0:10.0.0.5 | eth1:172.16.1.5 | lb01 |
web01 | eth0:10.0.0.7 | eth1:172.16.1.7 | web01 |
web02 | eth0:10.0.0.8 | eth1:172.16.1.8 | web02 |
1.配置两台web节点
web01
①配置nginx配置文件
[root@web01 ~]# cat /etc/nginx/conf.d/node.etiantian.org.conf
server {
listen 80;
server_name node.etiantian.org;
root /code/node;
location / {
index index.html;
}
}
[root@web01 ~]# mkdir /code/node
[root@web01 ~]# echo "web01..." > /code/node/index.html
[root@web01 ~]# nginx -t
[root@web01 ~]# systemctl reload nginx
②检查语句,重启服务
[root@web01 ~]# nginx -t
[root@web01 ~]# systemctl reload nginx
③添加索引文件
[root@web01 ~]# mkdir /code/node
[root@web01 ~]# echo "web01..." > /code/node/index.html
web02
①配置nginx配置文件
[root@web02 ~]# cat /etc/nginx/conf.d/node.etiantian.org.conf
server {
listen 80;
server_name node.etiantian.org;
root /code/node;
location / {
index index.html;
}
}
②检查语句,重启服务
[root@web02 ~]# nginx -t
[root@web02 ~]# systemctl reload nginx
③添加索引文件
[root@web02 ~]# mkdir /code/node
[root@web02 ~]# echo "web02..." > /code/node/index.html
2.配置负载均衡
①配置nginx配置文件
[root@lb01 ~]# cat /etc/nginx/conf.d/proxy_node.etiantian.org.conf
upstream node {
server 10.0.0.7:80;
server 10.0.0.8:80;
}
server {
listen 80;
server_name node.etiantian.org;
location / {
proxy_pass http://node;
include proxy_params;
}
}
②重启服务检查语句
[root@web01 ~]# nginx -t
[root@web01 ~]# systemctl reload nginx
3.配置DNS本地劫持
4.浏览器测试
打开谷歌浏览器访问node.etiantian.org
每刷新一次调度到不同的web节点上
5.抓包分析
👺4.nginx负载均衡对接wordpress(部署LNMP)
负载均衡要与后端web节点域名保持一致
在lb01配置负载均衡,把两台节点逻辑为一个逻辑组中进行调度
upstream blog {
server 172.16.1.7:80;
server 172.16.1.8:80;
}
server {
listen 80;
server_name blog.etiantian.org;
location / {
proxy_pass http://blog;
include proxy_params;
}
}
②浏览器测试
👺5.nginx负载均衡调度算法
调度算法 | 概述 |
---|---|
轮询 (静态调度算法 ) | 按时间顺序逐一分配到不同的后端服务器(默认) |
weight (静态调度算法) | 加权轮询,weight值越大,分配到的访问几率越高 |
ip_hash | 每个请求按照访问ip的hash结果分配,这样来自同一个ip的固定访问一个后端服务器 |
least_conn | 将请求传递到活动连接数最少的服务器 |
5.1 轮询算法 rr
应用场景
静态调度算法:根据用户的http请求,均匀分配给资源池各个应用节点
Nginx负载均衡轮询具体配置
upstream load_pass {
server 10.0.0.7:80;
server 10.0.0.8:80;
}
5.2 加权轮询 wrr
应用场景
硬件物理服务器配置不同,从而根据节点的权重比率来调度
Nginx负载均衡 [weight] 权重轮询具体配置
upstream load_pass {
server 10.0.0.7:80 weight=5;
server 10.0.0.8:80; weight=1;
}
5.3 ip_hash
①哈希算法原理
指定一个组应该使用负载平衡方法,其中请求基于客户端IP地址分布在服务器之间。客户端IPv4地址的前三个八进制数,或者整个IPv6地址,用作一个散列键。该方法确保来自同一客户端的请求将始终传递到同一服务器,除非该服务器不可用时。在后一种情况下,客户机请求将被传递到另一个服务器。最可能的情况是,它也将始终是同一台服务器。
②ip_hash的弊端
造成后端某一个应用节点压力过大,而其他节点没有流量。 解决方法就是引入我们的redis
③ip_hash的作用
可以解决会话的保持
5.4 url_hash
5.5 最少连接数 least_conn
👺6.Nginx负载均衡后端节点状态指标
状态 | 概述 |
---|---|
down | 当前的server暂时不参与负载均衡 |
backup | 预留的备份服务器 |
max_ fails | 允许请求失败的次数 |
fail_timeout | 经过max_fails失败后,服务暂停时间 |
max_conns | 限制最大的接受连接数 |
👺7.redis实现会话共享
7.1什么是会话保持?
当用户登陆一个网站服务器,网站服务器会将用户的登陆信息存储下来(存储下来的内容叫session),以保证我们能够一直处于“登陆在线”状态
7.2 为什么要实现会话保持
由于我们使用的是负载均衡轮询机制,会导致用户请求分散在不同的节点,从而造成会话无法保持。
假设用户A,通过负载均衡登陆了网站,此时会话信息存储在A节点,那么当它一刷新,负载均衡会将请求分发给B节点,那么B节点没有用户A的登陆信息,就会提示用户A登陆,当A用户点击登陆时又会将请求分发给C节点,从而造成用户A无法实现会话保持
7.3如何实现会话保持
1.粘性session:指nginx每次都将同一用户的所有请求转发至同一台服务器上,及Nginx的ip_hash
2.session复制:即每次session发生变化时,就广播给集群中的服务器,使所有的服务器上的session相同
3.session共享:缓存session至内存数据库中,使用redis,memcached实现
4.sessio持久化:将sessio存储至数据库中,像操作数控一样操作session。
👺部署redis实操
1.搭建环境(nginx+php)
2.运行phpadmin项目(数据库的web管理页面,通过web页面的方式管理数据库)
① 编写Nginx配置文件
[root@web01 ~]# cat /etc/nginx/conf.d/admin.etiantian.org.conf
server {
listen 80;
server_name admin.etiantian.org;
root /code/admin;
location / {
index index.php;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
②重启服务,检查语句
nginx -t
systemctl restart nginx
③上传代码,解压
[root@web01 ~]# unzip phpMyAdmin-5.0.4-all-languages.zip -d /code/ 解压到指点的/code目录路径下
[root@web01 ~]# ln -s /code/phpMyAdmin-5.0.4-all-languages/ /code/admin 创建一个软连接
④配置phpadmin(需要知道管理的是那一台数据库)
[root@web01 ~]# cp /code/admin/config.sample.inc.php /code/admin/config.inc.php
[root@web01 ~]# vim /code/admin/config.inc.php +32
$cfg['Servers'][$i]['host'] = '172.16.1.51'; # 仅修改这一行
⑤我们去给我们要存放session信息的路径授权
chown -R www.www /var/lib/php/session/
⑥配置本地DNS劫持,通过浏览器访问能否登陆成功
这边显示的是web01也就是我们的172.16.1.7通过内网去连接我们的数据库172.16.1.51.这里显示web01不是172.16.1.7是因为我在系统优化的时候配置了 /etc/hosts
3.新添加一个节点web02
因为两台节点的配置是一样的,所以我们可以直接把web01的配置复制过来使用
[root@web02 ~]# scp 172.16.1.7:/etc/nginx/conf.d/admin.etiantian.org.conf /etc/nginx/conf.d/
[root@web02 ~]# scp -r 172.16.1.7:/code/phpMyAdmin-5.0.4-all-languages /code/
[root@web02 ~]# ln -s /code/phpMyAdmin-5.0.4-all-languages/ /code/admin
[root@web02 ~]# chown -R www.www /var/lib/php/session/
[root@web02 ~]# nginx -t
[root@web02 ~]# systemctl reload nginx
①配置本地DNS劫持,通过浏览器去访问一下
这里显示的就是web02
4.添加负载均衡节点
配置负载均衡的nginx配置文件
[root@lb01 conf.d]# cat proxy_admin.etiantian.org.conf
upstream admin {
server 172.16.1.7:80;
server 172.16.1.8:80;
}
server {
listen 80;
server_name admin.etiantian.org;
location / {
proxy_pass http://admin;
include proxy_params;
}
}
配置dns本地劫持,通过浏览器测试
这个时候我们就会发现我们去登陆的时候,登陆不上去。并且会提示建立session会话不成功。 每新的刷新一次就会有一个新的session,因为负载均衡通过轮询的算法每次调度的节点不一样,每一台节点登陆时服务器会给一个属于它的session信息,负载均衡下次调度调度到别的节点,服务器发现和上次的节点session信息不匹配,就会产生一个新的session信息。那么接下来就有两种方法解决一种是ip_hash调度算法,一种是redis,将所有的web节点的session登陆信息存放在redis中
5.采用Nginx IP_hash解决测试
1.在lb节点配置
②通过浏览器测试
我们发现ip_hash虽然能够解决登陆会话的问题,但是ip_hash算法会把它固定的调度到一个web节点上,就发挥不出我们轮询节点的方式 ,所以我们还是采用redis方法才可以
6.采用redis共享方式来实现
①安装redis(在db数据库节点部署)
yum -y install redis
②更改配置文件
因为redis的监听端口默认在本地127.0.0.1:6379上,监听本地,只有自己可以访问,所以我们为了能够访问把它修改为监听在自己的内网网卡上。也就是172.16.1.0这个网段。
修改redis监听在自己的内网网卡上
[root@db01 ~]# sed -i '/^bind/c bind 127.0.0.1 172.16.1.51' /etc/redis.conf
然后重启服务,加入下次开机自启
nginx -t
systemctl restart redis
systemctl enable redis
③在web节点上配置php应用服务器的session信息存储至Redis中,有两个文件控制session信息写在哪里。一个是/etc/php.ini 一个是/etc/php-fpm.d/www.conf
我们在安装php时,依赖关系已经把php有关于redis的模块安装下来了,所以我们不需要再去安装
/etc/php.ini (两台web节点都要修改)
我们修改/etc/php.ini这个文件,指点session存储在哪里
[root@web01 ~]# vim /etc/php.ini
session.save_handler = redis
session.save_path = "tcp://172.16.1.51:6379?weight=1&timeout=2.5"
/etc/php-fpm.d/www.conf (两台web节点都要修改)
打开这个文件到末行,把倒数第二和倒数第三注释掉
#注释如下两行,使用;
[root@web01 ~]# vim /etc/php-fpm.d/www.conf
;php_value[session.save_handler] = files
;php_value[session.save_path] = /var/lib/php/session
重启php服务
systemctl restart php-fpm
④将负载均衡的ip_hash方法修改为轮询。通过浏览器访问
一次web01,一次web02 保持轮询的调度,而且会话保持登陆