在前面的课程中我们学习了如何使用LVS实现后端服务器的负载均衡,同时也学习了如何使用keepalived实现lvs分发器的负载均衡,本章我们一起来看一下另外一种可以帮助我们实现负载均衡的软件,这个软件就是nginx
知识点
传统web的访问模型及缺陷,并行处理解决方案
nginx集群的原理
如何使用nginx构建web集群
nginx的分发算法
主机头中都包含哪些信息
nginx的高级分发功能如何使用
keepalived的介绍及部署
如何构建nginx+keepalived高可用集群
课程目标
能够知道针对于传统模型的缺陷有哪些解决方案
能够说出nginx是如何实现集群功能的
能够说出nginx集群如何配置,有哪些算法,如何配置
能够说出基于主机头的分发都有哪些类型,如何实现
能够独立完成nginx+keepalived架构的搭建及配置
一 介绍
传统web访问模型
(1)传统web访问模型完成一次请求的步骤
1)用户发起请求
2)服务器接受请求
3)服务器处理请求(压力最大)
4)服务器响应请求(2)传统模型缺点
单点故障;
单台服务器资源有限(客户端则是无限的);
单台服务器处理耗时长(客户等待时间过长);(3)传统模型优化——单点故障解决方案
部署一台备份服务器,宕机直接切换该方案可以有效解决服务器故障导致的单点故障,但且服务器利用率低、成本高,切换不及时,且无法解决服务器业务压力问题。
并行处理解决方案
1)DNS轮询解析方案
通过dns服务器中添加多条A记录,将同一个域名分别解析为不同的IP地址,这样就实现了一个简单的负载均衡
优点:成本较低,如果你有多个公网IP的话,只需要在DNS上多添加几条A记录就可以了,公网IP需要收费,这个功能是不收费的;部署方便,只需要增加web服务即可,原架构不需要更改。每台主机的负载都是均衡的。
缺点:无法进行健康检查,如果有web服务器宕机,DNS服务器是无法知晓的,会影响业务,而且会暴露太多的公网IP,实效性不佳,修改DNS记录需要一个生效周期,有的是3-4个小时,有的会更久;分配不均,如果几台Web服务器之间的配置不同,能够承受的压力也就不同,但是DNS解析分配的访问却是均匀分配的。其实DNS也是有分配算法的,可以根据当前连接较少的分配、可以设置Rate权重分配等等,只是目前绝大多数的DNS服务器都不支持;会话保持,如果是需要身份验证的网站,在不修改软件构架的情况下,这点是比较致命的,因为DNS解析无法将验证用户的访问持久分配到同一服务器。虽然有一定的本地DNS缓存,但是很难保证在用户访问期间,本地DNS缓存不过期
2)多机阵列——集群模式
两台负载均衡主机一个为主服务器,另外一个为备用服务器,他们,正常情况下,主服务器会绑定一个虚拟IP(Virtual IP),DNS将域名解析为虚拟IP,客户端的请求到达负载均衡器后,由负载均衡将请求交给后端的web服务器,如果主服务器宕机,则备用服务器会自动绑定这个虚拟IP,继续进行分发工作,这一切对于用户而言是透明的
优点:不需要调整dns服务器,因为是用过相应的软件来实现负载均衡的,并且只需要一个公网IP地址做为虚拟IP就可以了,还能做到随时扩容,如果后端的web服务器宕机,负载均衡器会将其从分发列表里剔除,真正的实现的网站的高度可用,因为负载均衡器有备用服务机,web服务器也有备用机
缺点:软件上和硬件上都可以实现负载均衡,选择的时候要慎重,硬件上的设备需要资金投入,软件上的要根据自己的需求决定,如LVS不能实现动静分离;NGINX适用范围小,只能支持http,https等少数的协议;HAProxy不支持POT/SMTP协议,多进程模式不够好等。
集群
计算机集群简称集群,是一种计算机系统, 它通过一组松散集成的计算机软件或硬件连接起来高度紧密地协作完成计算工作。在某种意义上,他们可以被看作是一台计算机。 (百度解释)
将多个物理机器组成一个逻辑计算机,实现负载均衡和容错。
组成要素:
1)VIP: 给分发器的一个虚IP
2)分发器:nginx
3)数据服务器:web服务器nginx集群原理
在Nginx集群中Nginx扮演的角色是:分发器。
任务:接受请求、分发请求、响应请求。
功能模块:
1)ngx_http_upstream_module:基于应用层(七层)分发模块
2)ngx_stream_core_module:基于传输层(四层)分发模块(1.9开始提供该功能)nginx集群的实质
nginx 默认支持分发 他有一个自带模块 叫upstream 这就是nginx的分发模块,也就是说nginx分发是一个组合体 将什么组合在一起呢
虚拟主机+反向代理+upstream,在这个组合中
虚拟主机:负责接受和响应请求。
反向代理:带领用户去数据服务器拿数据。
upstream:告诉nginx去哪个数据服务器拿数据。数据包走向
1)用户发起请求
2)虚拟主机接受用户请求
3)虚拟主机去找反向代理(问反向代理去哪拿数据)
4)反向代理让去找upstream
5)upstream告诉一个数据服务器IP
6)Nginx去找数据服务器,并发起用户的请求
7)数据服务器接受请求并处理请求
8)数据服务器响应请求给Nginx
9)Nginx响应请求给用户
二 使用nginx分发器构建一个web集群
环境准备
实验机 :四台虚拟机,一台测试机,一台分发器,两台web服务器。
网卡:vmnet4
系统:CentOS8.0
SELinux&防火墙:关闭
网段:192.168.0.0/24
架构图
配置web业务机
部署nginx
nginx安装脚本
#!/bin/bash
nginx_pkg=nginx-1.15.12.tar.gz
nginx_prefix=/usr/local/nginx
html=/var/nginx
log=/var/log/nginx
check13 () {
[ $UID -ne 0 ] && echo “need to be root to that” && exit 1
[ ! -f $nginx_pkg ] && echo “not found source packager” && exit 1
[ ! -d $html ] && mkdir -p $html
[ ! -d $log ] && mkdir -p $log
}
nginx_install () {
source_pkg=`echo $nginx_pkg|awk -F “.tar” {print $1}`
[ -d /usr/src/$source_pkg ]&&rm -rf /usr/src/$source_pkg
tar xf $nginx_pkg -C /usr/src
cp nginxd /usr/src/$source_pkg
if [ $? -eq 0 ];then
cd /usr/src/$source_pkg
if [ $? -eq 0 ];then
dnf -y install gcc-* pcre pcre-devel zlib zlib-devel openssl-* make*&> /dev/null
[ $? -ne 0 ]&&”YUM set error” && exit 1
./configure –prefix=$nginx_prefix
if [ $? -eq 0 ];then
make
if [ $? -eq 0 ];then
make install
if [ $? -eq 0 ];then
ln -s -f $nginx_prefix/conf/nginx.conf /etc/
ln -s -f $nginx_prefix/logs/ $log/logs
ln -s -f $nginx_prefix/html $html/html
ln -s -f $nginx_prefix/sbin/ /usr/sbin/
cp nginxd /etc/init.d/nginx;chmod 755 /etc/init.d/nginx
else
exit 1
fi
else
exit 1
fi
else
exit 1
fi
else
exit 1
fi
else
exit 1
fi
[ $? -eq 0 ]&&clear||exit
echo -e “\n\033[32m Nginx Install Success: \033[0m”
echo -e “\n”
echo -e “\tNginx_conf: /etc/nginx.conf”
echo -e “\tNginx_html: $html/html”
echo -e “\tNginx_access_log: $log/logs/access.log”
echo -e “\tNginx_error_log: $log/logs/error.log\n\n\n\n”
read -n1 -p “press any key and exit….”
echo
}
check13
nginx_install我们在学习web服务时,涉及过nginx的安装,这个脚本只是将我们之前需要手动执行的工作变成了自动执行
脚本完成的工作
安装nginx需要用到的软件包
将nginx安装到/usr/local/nginx目录下
页面文件可直接放在/var/nginx目录下
日志文件可直接查看/var/log/nginx目录下
配置文件可直接编辑/etc/nginx.conf
配置web
web1
[root@web1 ~]# dnf -y install httpd
[root@web1 ~]# echo web1 > /var/www/html/index.html
[root@web1 ~]# systemctl restart httpd
[root@web1 ~]# curl localhost
web1
[root@web2 ~]# dnf -y install httpd
[root@web2 ~]# echo web2 > /var/www/html/index.html
[root@web2 ~]# systemctl restart httpd
[root@web2 ~]# curl localhost配置分发器
部署nginx分发器
[root@nginx ~]# sh nginx_install.sh
配置nginx
[root@nginx ~]# cd /usr/local/nginx/conf/
[root@nginx conf]# sed -i /#/d nginx.conf
[root@nginx conf]# sed -i /^$/d nginx.conf
[root@nginx ~]# vim /etc/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream web { # 名为web的反向代理群组
server 192.168.0.42;
server 192.168.0.43;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://web; # 去找反向代理
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}集群分发测试
[root@client ~]# curl 192.168.0.40
web1
[root@client ~]# curl 192.168.0.40
web2
[root@client ~]# curl 192.168.0.40
web1
[root@client ~]# curl 192.168.0.40
web2
停止一台主机的web服务
[root@web2 ~]# systemctl stop httpd
继续测试
[root@client ~]# curl 192.168.0.40
web1
[root@client ~]# curl 192.168.0.40
web1
[root@client ~]# curl 192.168.0.40
web1
由此可见nginx有自动检测后端真实服务器的功能,继续
启动web2这台主机的nginx服务,并停掉网卡
[root@web2 ~]# systemctl start httpd
[root@web2 ~]# nmcli connection down ens33
成功停用连接 “ens33″(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/1)
继续测试
[root@client ~]# curl 192.168.0.40
web1
[root@client ~]# curl 192.168.0.40
web1
[root@client ~]# curl 192.168.0.40
web1如果我把网卡down了,你会发现访问速度变慢 然后才能正常访问 因为down网卡相当于防火墙的DROP 知道等到超时为止
也就是说当nginx找upstream要数据的时候,upstream给nginx一个RS地址,nginx去联系这个地址发现联系不上,回去找upstream说你给我那玩意不好使,然后upstream说那我再给你一个吧,那这样的话用户永远都访问不到down掉的RS了,如果都不好使呢?你的网站就挂了。
三 nginx分发算法
集群分发算法:如何将用户请求按照一定的规律分发给业务服务器。主要分为Nginx集群默认算法和基于请求头分发算法。
nginx集群默认算法
nginx的upstream 目前支持4种方式的分配
(1)轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。用于处理静态页面
(2)weight
指定权重,数值大的服务器,获得的请求的数量越多,用于后端服务器性能不均的情况。用于处理静态页面
(3)ip_hash
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务,好处是可以解决session的问题。可以处理动态网站。(4)url_hash(第三方)
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务 ,后端服务器为缓存时比较有效。nginx有很多第三方模块,各位可以去下载使用
https://www.nginx.com/resources/wiki/modules/
nginx业务服务器状态
每个设备的状态设置参数:
down表示当前的server暂时不参与负载;
weight默认为1,weight越大,负载的权重就越大;
max_fails允许请求失败的次数默认为1,当超过最大次数时,返回proxy_next_upstream模块定义的错误;
fail_timeout失败超时时间,在连接Server时,如果在超时时间之内超过max_fails指定的失败次数,会认为在fail_timeout时间内Server不可用,默认为10s
backup其他所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。
nginx集群默认算法测试
环境
实验机 :四台虚拟机,一台测试机,一台分发器,两台web服务器。
网卡:vmnet4
系统:CentOS8.0
SELinux&防火墙:关闭
网段:192.168.0.0/24
架构
轮询算法
upstream web {
server 192.168.0.42;
server 192.168.0.43;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://web;
}
}前面已经测试验证了轮询算法分发。
配置backup参数
upstream web {
server 192.168.0.42;
server 192.168.0.43 backup;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://web;
}
}先正常访问测试
[root@client ~]# curl 192.168.0.40
web1
[root@client ~]# curl 192.168.0.40
web1
[root@client ~]# curl 192.168.0.40
web1关停第一个节点情况,访问尝试:
[root@web1 ~]# systemctl stop httpd
[root@client ~]# curl 192.168.0.40
web2
[root@client ~]# curl 192.168.0.40
web2
[root@client ~]# curl 192.168.0.40
web2启动第一个节点测试
[root@web1 ~]# systemctl start httpd
[root@client ~]# curl 192.168.0.40
web1
[root@client ~]# curl 192.168.0.40
web1
[root@client ~]# curl 192.168.0.40
web1基于权重
通过配置权重,可以让性能好的服务器承担更多的负载
upstream web {
# 设置权重比例1:2
server 192.168.0.42 weight=1;
server 192.168.0.43 weight=2;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://web;
}
}测试
[root@client ~]# curl 192.168.0.40
web1
[root@client ~]# curl 192.168.0.40
web2
[root@client ~]# curl 192.168.0.40
web2
[root@client ~]# curl 192.168.0.40
web1
[root@client ~]# curl 192.168.0.40
web2
[root@client ~]# curl 192.168.0.40
web2基于ip_hash分发
ip_hash算法能够保证来自同样源地址的请求都分发到同一台主机。 需要注意:ip_hash算法不支持backup、weight设置。默认权重为1。
upstream web {
ip_hash; # 指定ip_hash即可,默认weight权重比例1: 1
server 192.168.0.42;
server 192.168.0.43;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://web;
}
}测试
[root@client ~]# curl 192.168.0.40
web2
[root@client ~]# curl 192.168.0.40
web2
[root@client ~]# curl 192.168.0.40
web2
切换到另外一台不同网段的主机
MacBook-Pro:~ hello$ ifconfig
vmnet8: flags=8863
ether 00:50:56:c0:00:08
inet 172.16.121.1 netmask 0xffffff00 broadcast 172.16.121.255
MacBook-Pro:~ hello$ curl 172.16.121.134
web1
MacBook-Pro:~ hello$ curl 172.16.121.134
web1
MacBook-Pro:~ hello$ curl 172.16.121.134
web1基于url的hash
不同的URL我去找不同的机器访问,就是把url计算出一个值然后除以机器的数量取余 ,需要安装第三方插件
nginx分发器上,将nginx主程序包和下载好的第三方软件包放在同一个目录下解压
[root@master ~]# cd nginx-1.15.12/
[root@master ~]# ./configure –prefix=/usr/local/nginx –add-module=/root/ngx_http_consistent_hash-master
第三方模块的安装方法
[root@master ~]# make & make install
[root@master ~]# vim /usr/local/nginx/conf/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream web {
consistent_hash $request_uri;
server 192.168.0.42 ;
server 192.168.0.43 ;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://web;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
[root@master ~]# /usr/local/nginx/sbin/nginx
在web主机上生成测试页面
[root@web1 ~]# for i in `seq 1 10`; do echo “web1_$i” > /var/www/html/$i.html; done
[root@web2 ~]# for i in `seq 1 10`; do echo “web2_$i” > /var/www/html/$i.html; done
这样我们就知道测试的时候访问的是哪台机器的页面文件了
测试访问
[root@client ~]# for i in `seq 1 10`; do curl http://192.168.0.40/$i.html; done
web1_1
web1_2
web1_3
web2_4
web2_5
web1_6
web2_7
web1_8
web2_9
web2_10这个方式一般用在我们的缓存上,目的是为了命中率,什么是命中率,也就是说同样是下数据,你要是从源下就是没有命中,从缓存下就是命中
四 nginx基于请求头的分发
前面的分发方式都是基于一个集群分发的,nginx是一个基于7层的分发也就是可以实现基于主机头的分发,这种分发一般都是用于多集群环境中。
客户端浏览器开发者Request URL: http://192.168.0.40 #请求的URL
数据
Remote address:192.168.0.40:80#远程主机的地址
Status code: 200 OK #请求代码,200表示正常,如果页面无法打开会显示404,403等
Version: HTTP/1.1#HTTP协议的版本
Response headers (235 B) #响应头
Accept-Ranges:bytes#接受范围,如果出现此字段表示,这是一个续传的下载(断点续传),bytes表示服务器可接受范围请求的单位是bytes,none表示不支持
Connection:keep-alive #是否支持长连接,从HTTP1.1开始默认
Content-Length:5 #返回的数据长度,单位为字节
Content-Type:text/html#页面类型,文本、图片、视频、音频
Date:Fri, 21 Feb 2020 01:37:17 GMT#返回的时间
ETag:”5e4e2e62-5″#验证标签,用来帮助控制缓存验证,当浏览器请求服务器的某项资源(A)时, 服务器根据A算出一个哈希值,并通过 ETag 返回给浏览器,浏览器把对应的哈希值和A同时缓存在本地,当下次再次向服务器请求A时,会把这个哈希值发送给服务器,服务器再次计算A的哈希值并和刚刚接收到的哈希值做比较,如果发现A发生了变化就把A返回给浏览器(200),如果发现A没有变化就给浏览器返回一个304未修改。这样通过控制浏览器端的缓存,可以节省服务器的带宽,因为服务器不需要每次都把全量数据返回给客户端
Last-Modified:Thu, 20 Feb 2020 06:59:46 GMT#服务器认定的资源做出修改的日期及时间。 它通常被用作判断接收到的或者存储的资源是否一致。由于精确度比ETag要低,所以这是一个备用机制。
Server:nginx/1.15.12 #服务器的软件类型和版本
Request headers (355 B) #请求头
Accept:text/html,application/xhtml+xm… #接受的数据类型
Accept-Encoding:gzip, deflate #是否支持压缩,及类型
Accept-Language:en-US,en;q=0.5 #语言环境
Cache-Control:no-cache#缓存实现的机制。
Connection:keep-alive
Host:192.168.0.40#访问的名称(主机名还是IP地址),虚拟主机就是依靠这个字段来判断返回哪个页面内容
Pragma:no-cache#http1.0使用的字段,如果是no-cache与cache-control功能一致
Upgrade-Insecure-Requests:1 #客户端优先选择加密及带有身份验证的响应
User-Agent:Mozilla/5.0 (X11; Linux x86_64…) Firefox/60.0 #客户端浏览器类型和版本以上只是对在发者工具中看到的内容进行的说明,有需要的同学,或者是如果以后看到了其它额外字段的内容可以参看https://developer.mozilla.org/zh-CN/docs/Web/HTTP,里面有详细的说明
基于host分发
基于host分发这种分发方式适用于多集群分发。例如:一个公司有多个网站,每个网站就是一个集群。
#nginx分发器设置
http {
upstream web1 { # 名为web1的反向代理群组
server 192.168.0.42;
}
upstream web2 { # 名为web2的反向代理群组
server 192.168.0.43;
}
server { # web1虚拟主机
listen 80;
server_name www.web1.com; # 基于域名分发必须有域名
location / {
proxy_pass http://web1;
}
}
server { # web2虚拟主机
listen 80;
server_name www.web2.com; # 基于域名分发必须有域名
location / {
proxy_pass http://web2;
}
}
}基于域名的分发测试:
#客户端测试机设置
[root@client ~]# vim /etc/hosts
168.0.40 www.web1.com
192.168.0.40 www.web2.com
[root@client ~]# curl www.web1.com
web1
[root@client ~]# curl www.web2.com
web2基于开发语言分发
这种分发方式适用于混合开发的网站,某些大型网站既有php也有jsp,就可以基于开发语言分发。
# 192.168.0.40分发器上nginx配置
http {
upstream php {
server 192.168.0.42;
}
upstream html {
server 192.168.0.43;
}
server {
location ~* \.php$ { # 以php结尾的
proxy_pass http://php;
}
location ~* \.html$ { # 以html结尾的
proxy_pass http://html;
}
}
}测试验证:
# 在web1这台主机上安装php环境
[root@web1 ~]# dnf -y install php# 安装php
# 启动apache,自带php
[root@web1 ~]# systemctl restart httpd
# 编写php文件
[root@web1 ~]# echo “” > /var/www/html/index.php
# 访问192.168.0.40/index.php 可以看到php-info信息页面
# 访问192.168.0.40/index.html 可以看到web2基于浏览器分发
这种基于浏览器的分发,常应用于PC端和移动端区分或浏览器适配。
部署第三台业务主机
[root@web3 ~]# dnf install httpd -y
[root@web3 ~]# echo web3 > /var/www/html/index.html
[root@web3 ~]# systemctl restart httpd
[root@web3 ~]# curl localhost配置基于浏览器的分发
upstream curl { server 192.168.0.42; }
upstream firefox { server 192.168.0.43; }
upstream other { server 192.168.0.44; }
server {
listen 80;
server_name www.web1.com;
location / {
proxy_pass http://other;
if ( $http_user_agent ~* curl ) {
proxy_pass http://curl;
}
if ( $http_user_agent ~* firefox ) {
proxy_pass http://firefox;
}
}
}测试
使用不同的浏览器访问分发器会得到不同的页面
基于源IP分发
像腾讯新闻,网易,58同城,真爱,百合,赶集,智联等等很多网站,这种网站都有一个特性,你一访问,就知道你的位置,然后根据你的位置,给你推荐或者展示相关内容。很多APP也是这样的,只不过,网站是通过你的源IP来确定你的位置,APP的则;如果判断不出来,就按照默认去处理。如果想实现基于源IP的分发我们需要一个叫geo的参数,这个参数可以要根据客户端ip访问到不同的server,它是通过一个叫ngx_http_geo_module模块提供的。默认情况下,nginx安装时是会自动加载这个模块,除非安装时人为的手动添加–without-http_geo_module。
配置
upstream bj.server {
server 192.168.0.42; # web01
}
upstream sh.server {
server 192.168.0.43; # web02
}
upstream default.server {
server 192.168.0.44; # web03
}
geo $geo { # IP库
default default;
192.168.0.10/32 bj; # 北京
192.168.0.20/32 sh; # 上海
}
server {
listen 80;
server_name www.web1.com;
location / {
proxy_pass http://$geo.server$request_uri;
}
}如果客户端地址是0.10 就访问北京,如果是0.20就访问上海,如果不是0.10也不是0.20就按照default处理,线上环境这里面就是个IP库 我现在没有ip库只能写两个IP来代表看下后面的掩码是32表示这一个网段只有这一个IP吧,当然你也可以换成网段。
http后面加上$request_uri的原因就是避免客户 找你拿数据的时候一指定URI你就无法正常代理了,目的就是保证客户在访问类似http://www.a.com/a/b/c/d.jpg这样的网址的时候可以正常访问 也就是说当用户请求的URL当中的URI跟着变化的时候你的代理服务器一样可以正常工作
重启nginx服务器,切换到客户端测试
[root@client ~]# ifconfig
ens33: flags=4163
inet 192.168.0.10 netmask 255.255.255.0 broadcast 192.168.0.255
inet6 fe80::2386:3dbd:531c:7bc1 prefixlen 64 scopeid 0x20
ether 00:0c:29:a6:ad:95 txqueuelen 1000 (Ethernet)
RX packets 1177 bytes 280850 (274.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1115 bytes 111602 (108.9 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10
loop txqueuelen 1000 (Local Loopback)
RX packets 7080 bytes 601912 (587.8 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 7080 bytes 601912 (587.8 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@client ~]# curl 192.168.0.40
web1
[root@client ~]# nmcli connection modify ens33 ipv4.addresses 192.168.0.20/24 ipv4.method manual autoconnect yes
[root@client ~]# nmcli connection down ens33
成功停用连接 “ens33″(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/16)
[root@client ~]# nmcli connection up ens33
连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/17)
[root@client ~]# curl 192.168.0.40
web2
[root@client ~]# nmcli connection modify ens33 ipv4.addresses 192.168.0.30/24 ipv4.method manual autoconnect yes
[root@client ~]# nmcli connection down ens33
成功停用连接 “ens33″(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/17)
[root@client ~]# nmcli connection up ens33
连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/18)
[root@client ~]# curl 192.168.0.40
web3五 什么是高可用
通过前面课程的学习,我们知道nginx可以实现很多种不同类型的分发,我们还知道,集群系统存在的作用就是为了解决单点故障的问题。
nginx集群的单点故障问题
这个单点故障主要体现在两个方面
分发器宕机怎么处理?假如nginx服务器挂掉了,那么所有的服务也会跟着瘫痪 。一种方法是人为监控,发现主分发器宕机后,立马登录备分发器,并给它分配虚ip。
另一种办法是用软件来替代人来监控,自动登录备分发器,分配虚ip。
数据服务器宕机怎么处理?分发器可以自动判断数据服务器的存活状态,不对宕机服务器要数据。
keepalived介绍
keepalived是使用C语言编写的路由热备软件,该项目主要目标是为linux系统提供简单高效的负载均衡及高可用解决方案。keepalived由一组检查器,根据服务器的健康状况动态的维护和管理服务器池,另外keepalived通过vrrp协议实现高可用架构,vrrp是路由灾备的实现基础。通过前面的课程我们知道,在nginx中只解决了真实服务器的单点故障,但是如果分发器也就是nginx主机发生故障的话,整个集群系统都会崩溃,所以我们需要keepalived来实现集群系统的高可用。我们可以部署两台或更多的分发器,仅有一台调度器做为主服务器,其它的做为备用,当主调度器发生故障时,keepalived可以自动将备用调度器升级为主调度器,从而实现整个集群系统的高负载,高可用。
vrrp介绍
vrrp协议是为了静态路由环境下防止单点故障而设计的主从灾备协议,在主设备发生故障时业务自动切换至从设备,而这一切对于用户而言是透明的。vrrp将两台或多台设备虚拟成一个设备,对外仅提供一个虚拟的IP地址,这些设备在同一时刻仅有一台设备可有拥有该IP地址,而拥有该IP地址的设备就是主设备,其它的就是备用设备。主设备会不断发送自己的状态信息给备用设备,当备用设备接收不到主设备的状态信息时,多个备用设备会根据自身的优先级选择出新的主设备,并拥有所有的业务功能。vrrp协议需要为每个路由设备定义一个虚拟路由ID(VRID)以及优先,所有主备路由设备的VRID必须一样,这样才会被视为同一组设备,而优先级最高的设备就是主路由设备,VRID和优先级的范围为0-255之间的整数,数值越大优先级越高,如果优先级相等,则会对比IP地址,地址越大优先级越高
keepalived部署
部署keepalived
[root@master ~]# dnf install keepalived -y
[root@backup ~]# dnf install keepalived -y配置文件说明
[root@lvs1 ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs { #全局配置
notification_email { #指定keepalived在发生切换时需要发送email到的对象,一行一个
[email protected] #指定收件人邮箱
}
notification_email_from [email protected] #指定发件人
smtp_server 192.168.200.1 #指定smtp服务器地址
smtp_connect_timeout 30 #指定smtp连接超时时间
router_id LVS_DEVEL #此处注意router_id为负载均衡标识,在局域网内应该是唯一的。
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 { #虚拟路由的标识符
state MASTER #状态只有MASTER和BACKUP两种,并且要大写,MASTER为工作状态,BACKUP是备用状态
interface eth0 #通信所使用的网络接口
virtual_router_id 51 #虚拟路由的ID号,是虚拟路由MAC的最后一位地址
priority 100 #此节点的优先级,主节点的优先级需要比其他节点高
advert_int 1 #通告的间隔时间
authentication { #认证配置
auth_type PASS #认证方式
auth_pass 1111 #认证密码
}
virtual_ipaddress { #虚拟ip地址,可以有多个地址,每个地址占一行,不需要子网掩码,同时这个ip 必须与我们在lvs 客户端设定的vip 相一致!
192.168.200.16
192.168.200.17
192.168.200.18
}
}
virtual_server 192.168.200.100 443 { #集群所使用的VIP和端口
delay_loop 6 #健康检查间隔,单位为秒
lb_algo rr #lvs调度算法rr|wrr|lc|wlc|lblc|sh|dh
nat_mask 255.255.255.0 #VIP掩码
lb_kind NAT #负载均衡转发规则。一般包括DR,NAT,TUN 3种
persistence_timeout 50 #会话保持时间,会话保持,就是把用户请求转发给同一个服务器,不然刚在1上提交完帐号密码,就跳转到另一台服务器2上了
protocol TCP #转发协议,有TCP和UDP两种,一般用TCP,没用过UDP
real_server 192.168.200.100 443 { #真实服务器,包括IP和端口号
weight 1 #权重
TCP_CHECK { #通过tcpcheck判断RealServer的健康状态
connect_timeout 3 #连接超时时间
nb_get_retry 3 #重连次数
delay_before_retry 3 #重连间隔时间
connect_port 23 #健康检查的端口的端口
bindto
}
HTTP_GET { #健康检测方式,可选有 SSL_GET、TCP_CHECK、HTTP_GET
url { #检查url,可以指定多个
path / #检查的url路径
digest ff20ad2481f97b1754ef3e12ecd3a9cc #需要检查到的内容。检查后的摘要信息。
}
url {
path /mrtg
digest 9b3a0c85a887a256d6939da88aabd8cd
}
url {
path /testurl3/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
connect_timeout 3 #连接超时时间
nb_get_retry 3 #检测尝试几次
delay_before_retry 3 #检测的时间间隔
}
}
}
[root@master ~]# systemctl start keepalived.service
[root@backup ~]# systemctl start keepalived.servicekeepalived有三个功能 管理VIP 管理分发规则 管理RS,在nginx当中RS,也就是真实服务器,不需要keepalived管理,因为nginx自己能管理,所以我们需要keepalived做的工作就是,管理VIP和判断分发器是否正常
这里面有一个问题需要弄清楚,在lvs+keepalived的架构中,如果lvs挂了,keepalived肯定挂,因为lvs是基于内核的功能,如果lvs挂了,那就意味着内核挂了,内核要是挂了,整个操作系统中谁都跑不了,全都得跟着去了。所以当keepalived出现问题后VIP就会被释放,而备用分发器就会绑定这个VIP;但是nginx都是属于七层的服务,他们之间没有依存关系,那么如果nginx挂了keepalived还活着的话,这个VIP就不会被释放,备用服务器也就无法绑定这个VIP,此时集群就会出现问题,绑定VIP的主机,不能正常分发客户端请求;能够分发客户端请求的主机,没有VIP。为了避免这种情况出现我们就需要通过一个脚本让keepalived去检测nginx状态,如果发现nginx死了就自杀,这样keepalived就没法向网络中发组播了,同时也会释放VIP。而上面我们所提到的那种尴尬的情况也就不会出现了。所以各位要记住lvs+keepalived的关联是通过依存关系,而nginx+keepalived就是通过脚本
六 构建高可用集群
实验环境准备
架构
配置nginx集群
master&backup安装nginx和keepalived
修改nginx配置文件
[root@master ~]# vim /usr/local/nginx/conf/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
upstream web {
server 192.168.0.42 max_fails=2 fail_timeout=3;#3秒内失败2次,则认为此节点失效
server 192.168.0.43 max_fails=2 fail_timeout=3;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://web;
}
}
}配置keepalived
[root@master ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id NGINX_DEVEL
}
vrrp_script check_nginx { #定义脚本的名称为check_nginx
script “/etc/keepalived/nginx_pid.sh” #检查对应位置的文件是否存在
interval 2 #定义执行间隔为2秒
fall 1 #失败次数为1次
}
vrrp_instance nginx { #定义实例名称为nginx
state MASTER #定义主机状态
interface ens33 #定义通信接口,VIP绑定的接口
mcast_src_ip 192.168.0.40 #定义发送vrrp广播的源地址,模式使用VIP绑定网卡的主IP地址
virtual_router_id 51#定义VRID,主从设备vrid要抑制
priority 100#定义优先级
advert_int 1 #定义检查间隔,默认1秒
authentication { #设置认证,同一vrid的设备要抑制
auth_type PASS #认证方式为PASS
auth_pass 1111 #认证密码为1111
}
track_script {
check_nginx #调用在vrrp_script中定义的内容
}
virtual_ipaddress {
192.168.0.150/24
}
}
[root@backup ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id NGINX_DEVEL
}
vrrp_script check_nginx {
script “/etc/keepalived/nginx_pid.sh”
interval 2
fall 1
}
vrrp_instance nginx {
state BACKUP
interface ens33
mcast_src_ip 192.168.0.41
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
check_nginx
}
virtual_ipaddress {
192.168.0.150/24
}
}构建关联脚本
[root@master ~]# vim /etc/keepalived/nginx_pid.sh
#!/bin/bash
nginx_kp_check () {
nginxpid=`ps -C nginx –no-header |wc -l`
if [ $nginxpid -eq 0 ];then
/usr/local/nginx/sbin/nginx
sleep 1
nginxpid=`ps -C nginx –no-header |wc -l`
if [ $nginxpid -eq 0 ];then
systemctl stop keepalived
fi
fi
}
nginx_kp_check
[root@backup ~]# vim /etc/keepalived/nginx_pid.sh
#!/bin/bash
nginx_kp_check () {
nginxpid=`ps -C nginx –no-header |wc -l`
if [ $nginxpid -eq 0 ];then
/usr/local/nginx/sbin/nginx
sleep 1
nginxpid=`ps -C nginx –no-header |wc -l`
if [ $nginxpid -eq 0 ];then
systemctl stop keepalived
fi
fi
}
nginx_kp_check
脚本功能说明:统计nginx进程数量,如果进程数量的值等于0,说明nginx挂了,那么执行/usr/local/nginx/sbin/nginx去启动分发器,等待1秒后再次检查进程数量,如果进程数量的值还是等于0,则执行systemctl stop keepalived停止keepalived服务。这样就停止发组播,释放VIP,而备用服务器就开始接手工作了。分发器宕机测试
使用客户端正常访问VIP
[root@client ~]# curl 192.168.0.150
web1
[root@client ~]# curl 192.168.0.150
web2在master上down掉nginx服务
[root@master ~]# watch -n1 killall nginx
每隔秒执行一次killall nginx命令
[root@master ~]# ip add #查看VIP是否还在
[root@backup ~]# ip add #到backup主机上查看是否有VIP继续测试
[root@client ~]# curl 192.168.0.150
web1
[root@client ~]# curl 192.168.0.150
web2重启master上的keepalived服务
[root@master ~]# ip add #查看VIP是否飘回来
[root@master ~]# lsof -i :80 #查看nginx是否被启再次测试
[root@client ~]# curl 192.168.0.150
web1
[root@client ~]# curl 192.168.0.150
web2数据服务器宕机测试
停止web1主机上的web服务
[root@web1 ~]# systemctl stop httpd
切换到client主机测试
[root@client ~]# curl 192.168.0.150
web2
[root@client ~]# curl 192.168.0.150
web2启动web1主机上的web服务
[root@web1 ~]# systemctl start httpd
切换到client主机测试
[root@client ~]# curl 192.168.0.150
web2
[root@client ~]# curl 192.168.0.150
web1总结
传统web的访问模型及缺陷,并行处理解决方案
nginx集群的原理
如何使用nginx构建web集群
nginx的分发算法
nginx的高级分发功能
keepalived的介绍及部署
如何构建nginx+keepalived高可用集群
ginx+keepalived架构的实现流程
难点:理解nginx集群的实现及测试方法、算法、主机头包含的信息,理解不同类型的高可用架构的差异,记住nginx+keepalived架构的实现及测试流程
命令输入部分没有使用”引用”功能,因为这个在线编辑工具会很智能的把编辑好的所有内容都应用上,不管你是否选中。