目录
前瞻导读
本文用于记录Nginx的知识点,学习该章节需要一定的linux基础,学习过程中的操作都基于Centos7,且使用Xshell远程连接虚拟机进行操作,Nginx使用nginx-1.24.0版本,虚拟主机node0的IP为192.168.70.155,虚拟主机node1的IP为192.168.70.156,大家在跟练的时候一定要将例子中的IP换成自己对应虚拟主机的IP。
在学习的过程中如果需要使用浏览器访问测试IP/域名/端口等任务时,推荐使用google浏览器,目前已知edge浏览器会将http协议自动转换成https,妨碍测试进度,因此不推荐edge。
1、Nginx是什么
Nginx (engine x) 是一款是由俄罗斯的程序设计师Igor Sysoev所开发高性能的Web和反向代理服务器。Nginx 是一个很强大的高性能 Web 和反向代理服务器,它具有很多非常优越的特性:在连接高并发的情况下,Nginx 是 Apache 服务不错的替代品。
1、 Nginx ("engine x") 是一个高性能的 静态HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器。
2、 其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名
3、 官方测试nginx能够支撑5万并发链接,并且cpu、内存等资源消耗却非常低,运行非常稳定
4、 事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:某浪、某易、某讯、某里等诸多大厂。
2、Nginx的作用
- 服务的反向代理
- 在反向代理中配置集群的负载均衡
- 在反向代理中配置集群的动静分离
- 搭建虚拟主机
代理服务器根据其代理对象的不同,可以分为正向代理服务器与反向代理服务器。这里的“正”与“反”均是站在客户端角度来说的。
2.1、正向代理
正向代理是对客户端的代理。客户端 C 想要从服务端 S 获取资源,但由于某些原因不能直接访问服务端,而是通过另外一台主机 P 向服务端发送请求。当服务端处理完毕请求后,将响应发送给主机 P,主机 P 在接收到来自服务端的响应后,将响应又转给了客户端 C。此时的主机 P,就称为客户端 C 的正向代理服务器。
客户端在使用正向代理服务器时是知道其要访问的目标服务器的地址等信息的。正向代理服务器是为服务用户(客户端)而架设的主机,对与服务器端来说是不知道正向代理服务器的存在。
2.2、反向代理
反向代理以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。
3、Nginx下载与安装
3.1、下载
Nginx官网:http://nginx.org
进入官网后,首先点击右侧的download
进入download界面后,最好选择Stable version或者Legacy version中的任意版本,这里我选择了Stable version中的nginx-1.24.0 pgp
3.2、安装
3.2.1、依赖安装
安装nginx需要先将官网下载的源码进行编译,编译依赖gcc环境,如果没有gcc环境,需要安装gcc。
yum install -y gcc make automake
PCRE是一个Perl库,包括 Perl 兼容的正则表达式库。nginx的http模块使用Pcre来解析正则表达式,所以需要在linux上安装Pcre库。
yum install -y pcre pcre-devel
zlib库提供了很多种压缩和解压缩的方式,nginx使用zlib对http包的内容进行gzip,所以需要在linux上安装zlib库。
yum install -y zlib zlib-devel
OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用。nginx不仅支持http协议,还支持https(即在ssl协议上传输http),所以需要在linux安装openssl库。
yum install -y openssl openssl-devel
统一安装依赖环境命令:
yum -y install gcc make automake pcre-devel zlib zlib-devel openssl openssl-devel
3.2.2、Nginx源码安装
首先我们在/opt/下新建目录apps用于存放下载的文件:
cd /opt
mkdir apps
然后我们进入到新建的文件夹apps中,将我们之前下载的Nginx包拖入到文件夹中,如果无法拖入,可以通过以下命令下载支持拖入的拓展:
yum -y install lrzsz
接下来通过以下命令对压缩文件进行解压(由于所下载的压缩文件版本可能存在差异,因此输入nginx文件名时可通过Tap键自动补全):
tar -zxvf nginx-1.24.0.tar.gz
解压完成后,进入解压后的nginx文件夹中,我们发现并没有编译需要的Makefile文件
此时,我们能通过如下命令查看nginx的配置参数:
./configure --help
接下来创建如下路径:/var/temp/nginx/client用于存放http相关配置,并开始对configure文件进行配置(右斜杠表示语句未结束暂不开始执行命令):
mkdir -p /var/temp/nginx/client
./configure \
--prefix=/usr/local/nginx \
--pid-path=/usr/local/nginx/logs/nginx.pid \
--error-log-path=/usr/local/nginx/logs/error.log \
--http-log-path=/usr/local/nginx/logs/access.log \
--with-http_ssl_module \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/temp/nginx/client \
--http-proxy-temp-path=/var/temp/nginx/proxy \
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi
配置完成后,我们能发现原本没有Makefile文件的nginx已经创建出了该文件:
有了编译需要的Makefile文件后,就可以编译并安装Nginx了:
make&&make install
等待命令执行结束,源码安装的Nginx就安装完毕了。
4、Nginx目录
由于在安装Nginx时我们通过--prefix=/usr/local/nginx配置了nginx的安装路径为/usr/local/nginx,因此进入该路径查看有哪些目录:
conf目录主要存放Nginx配置文件,学习阶段主要涉及conf目录中的nginx.conf文件:
html目录主要存放默认站点(默认是首页和服务器错误页):
logs目录存放Nginx的日志文件,如果安装完成后未启动过该目录中不会有任何文件,启动后会生成三个文件:
access.log #记录正常访问的日志
error.log #错误日志
nginx.pid #nginx进程id
sbin目录用于存放Nginx命令的目录,其中的nginx是用于启动nginx的脚本文件。
5、Nginx启动与关闭
5.1、Nginx启动
开启Nginx前需要先关闭防火墙(防火墙会杀死很多端口,为了防止受到防火墙的影响,需要提前关闭防火墙):
# 临时关闭防火墙
systemctl stop firewalld
# 永久关闭防火墙
systemctl disable firewalld
通过如下命令找到本虚拟机的ip,用于启动Nginx后访问浏览器页面,如果记得虚拟机ip可跳过:
vim /etc/sysconfig/network-scripts/ifcfg-ens33
文件中的IPADDR对应的就是虚拟机ip
完成以上步骤后就可以开启Nginx了:
# 进入如下目录(nginx安装目录下的sbin目录)/usr/local/nginx/sbin
cd /usr/local/nginx/sbin
# 通过调用sbin目录下的nginx脚本文件就可以启动nginx了
./nginx
启动完成后并不会有明显的反馈,可用如下命令查看是否有两个nginx进程:
ps aux|grep nginx
接下来我们打开浏览器,在浏览器地址栏中输入虚拟机ip查看是否能进入nginx首页:
至此,我们的Nginx就启动完成了。
5.2、Nginx关闭
5.2.1、立即停止
该方式无论进程是否在工作,都直接停止进程。
./nginx -s stop
5.2.2、从容停止
该方式需要进程完成当前工作后再停止。
./nginx -s quit
5.2.3、杀死进程
直接杀死nginx进程,在其他方式无效的情况下使用。
killall nginx
如果反馈未找到killall命令,通过以下命令添加,添加完成后再执行killall命令:
yum install psmisc
6、设置开机自启
如果每次都需要进入到Nginx目录启动效率较低,这时就可以考虑设置开机自启(这里所说的开机自启不仅是开机后就打开Nginx,而且不需要进入到Nginx的sbin目录下启动或关闭nginx,在任何位置都能通过特定的命令更加灵活的开启或关闭Nginx)。
设置开机自启需要进入系统服务添加自启动文件路径,首先需要进入系统服务创建服务文件nginx.service(该文件的文件名随意,这里是方便理解所取的名字)
cd /usr/lib/system/system/
vim nginx.service
nginx.service配置内容如下:
[Unit]
Description=nginx - high performance web server
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
[Install]
WantedBy=multi-user.target
配置完成后为该文件添加执行权限:
通过systemctl为nginx.service文件添加自启动:
# 为nginx开启自启动
systemctl enable nginx.service
# 查看nginx文件是否开启自启动
systemctl list-unit-files |grep nginx.service
至此,Nginx自启动就设置完成了,以后启动Nginx就可以通过以下命令直接启动/关闭:
启动nginx服务:systemctl start nginx
关闭nginx服务:systemctl stop nginx
停止开机自启动:systemctl disable nginx
查看服务当前状态: systemctl status nginx
重新启动服务: systemctl restart nginx
查看所有已启动的服务:systemctl list-units --type=service
7、Nginx配置文件块
进入Nginx的安装目录/usr/local/nginx/conf,打开其中的nginx.conf文件:
如上图,可以看到配置文件分为三个块,分别是全局块,event块和http块。
全局块中worker_processes用于指定nginx : worker process,一般由Nginx服务器的核数决定,如果Nginx为10核心,那么worker_processes一般设置为9,剩下的一核心用于预留给系统。
event块中worker_connections用于指定单个后台worker process进程的最大并发链接数,一般用于nginx工作模式的配置。
http块用于进行http协议信息的一些配置。
如下图,这是http块中的内容,我们可以将前三行理解为一个自定义函数,这个函数规定了日志记录的格式,图中最后一行可以理解为函数调用,如果我们只需要其中的一部分信息是可以copy前三行重命名后修改成我们需要的内容,然后在图中的最后一行将引用的名字改为我们重命名的名字即可以我们需要的格式进行日志记录。
如下图,这也是http块内的内容,keepalive_timeout 0表示如果同一用户无论在多长时间内不断发来多少个请求,Nginx都会对真实的服务器做轮询,让不同的服务器去处理同一用户的不同请求;keepalive_timeout 65表示同一用户在65秒内发来的不同请求集中在一台真实的服务器上处理。
如下图,gzip用于开启压缩文件,开启后会压缩文件大小:
http块又包含server块,每个server块就是一台虚拟机,一般用于进行服务器访问信息的配置:listen表示监听的端口,server_name用于连接的域名或者直接填入ip地址。
由上图可知,server块中还包含location块,location块主要用于进行访问路由的配置。
8、虚拟主机
概念:虚拟主机是一种特殊的软硬件技术,它可以将网络上的每一台计算机分成多个虚拟主机,每个虚拟主机可以独立对外提供www服务,这样就可以实现一台主机对外提供多个web服务,每个虚拟主机之间是独立的,互不影响的。
Nginx支持三种类型的虚拟主机配置:基于IP的虚拟主机,基于端口的虚拟主机,基于域名的虚拟主机。
8.1、基于IP的虚拟主机
Linux操作系统允许绑定多IP。在一块物理网卡上可以绑定多个lP地址,这样就能在使用单一网卡的同一个服务器上运行多个基于IP的虚拟主机。但是在绑定多IP时需要将动态的IP分配方式修改为静态的指定IP。
实操理解任务:将Linux服务器绑定两个IP,192.168.70.155和192.168.70.165 ,不同的IP请求不同的html目录,即访问http://192.168.70.155时将访问“html155”目录下的html网页,访问http://192.168.70.165时将访问“html165”目录下的html网页(在这个练习中,大家最好将题目中的IP地址换为自己虚拟主机的IP地址,防止测试不成功,例如:我都虚拟主机IP地址是192.168.70.155,那么我要设置的另一个IP为192.168.70同网段的任意IP即可)
强烈建议:在操作前,建议为虚拟机拍摄快照,方便后期将虚拟机恢复到现有状态去尝试不同的虚拟主机搭建方式,不用手动去恢复(后期我也是通过快照恢复到现有状态切换其他方式搭建虚拟主机)。
接下来正式开始实操,我们需要通过如下命令将IP分配方式修改为静态分配,并将目标IP添加到文件中:
vim /etc/sysconfig/network-scripts/ifcfg-ens33
# 修改内容
BOOTPROTO=static
IPADDR0=192.168.70.155
IPADDR1=192.168.70.165
可对照上述命令参考下图:
修改完成后重启网络服务或重启虚拟机使修改的文件内容生效:
# 重启网络服务
service network restart
# 重启虚拟机
reboot
更新完成后可通过ping命令去测试配置是否成功:
准备工作做完后,进入到/usr/local/nginx/conf目录对配置文件进行修改:
# 进入Nginx配置文件目录
cd /usr/local/nginx/conf
# 修改Nginx配置文件
vim nginx.conf
为了测试结果明显,我们将keepalive_timeout设置为0,如下图:
由于需要绑定两个IP的虚拟机,因此http块内的server块需要两个,复制整个server块并紧跟着server块粘贴,如下图(这里为了显示一目了然,删除了注释):
将server_name修改为对应的IP,以及不同IP对应不同的页面跳转,如下图:
防止迷糊,修改完成后的nginx.conf文件内容如下:
#user nobody;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 0;
#keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name 192.168.70.155;
location / {
root html155;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 80;
server_name 192.168.70.165;
location / {
root html165;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
为了测试方便,直接将Nginx目录下的html目录复制两份改名为html155和html165,再修改index中的内容就完成了不同页面的准备,如下图:
index.html文件只是用于展示我们的测试结果,所以一切从简,我们就在原有代码的基础上只留下body标签中的h1标签,并将内容修改为带有192.168.70.155信息即可,参考下图:
再对html165目录中的index.html进行相同的操作即可,只要页面能带有指定IP信息即可。
由于我们之前做了Nginx开机自启,因此这里需要重启Nginx,让配置文件生效:
systemctl restart nginx
打开浏览器,在地址栏中输入192.168.70.155,结果如下:
在地址栏输入192.168.70.165,结果如下:
至此,基于IP的虚拟主机演示案例就圆满完成了。
8.2、基于端口的虚拟主机
只要理清了基于IP的虚拟主机搭建过程,基于端口的虚拟主机基本也是换汤不换药,首先我们直接通过快照恢复到8.1节强烈建议中要求的拍摄快照处(如果没有跟着8.1节操作可忽略此话):
实操理解任务:Nginx提供8888与9999两个端口的监听服务,当请求8888端口时会访问html8888目录下的index.html,当请求9999端口时则会访问html9999目录下的index.html。
由于只涉及端口号的不同,因此不用像基于IP的虚拟主机一样修改网络配置文件,可直接开始修改/usr/local/nginx/conf/目录下的nginx.conf文件:
# 进入到Nginx的配置为念目录
cd /usr/local/nginx/conf/
# 修改Nginx配置文件
vim nginx.conf
首先还是为了演示的效果明显,将keepalive_timeout设置为0:
将http块中的server块复制一份粘贴到原有server块的后面,如下图:
接下来,通过listen设置端口号,server_name设置访问IP,location块中的root后面紧跟着不同端口号进入的不同界面(由于是基于端口的虚拟主机,所以IP不用变,两台主机IP相同):
防止迷糊,在此贴出修改后的nginx.conf配置文件源码:
#user nobody;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 0;
server {
listen 8888;
server_name 192.168.70.155;
location / {
root html8888;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 9999;
server_name 192.168.70.155;
location / {
root html9999;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
参考基于IP的虚拟主机练习的思路,将Nginx目录下的html目录复制两份改名为html8888和html9999,再修改index中的内容就完成了不同页面的准备,如下图:
在原有代码的基础上,除body标签中的h1标签留下外,其他标签全部删除,并将h1标签的内容修改为带有8888端口特征的内容,方便测试一目了然。
再对html9999目录下的index.html文件进行相同的操作,除body标签中的h1标签留下外,其他标签全部删除,并将h1标签的内容修改为带有9999端口特征的内容:
重启Nginx服务:
systemctl restart nginx
打开浏览器,在地址栏中输入192.168.70.155:8888 ,结果如下:
在地址栏中输入192.168.70.155:9999,结果如下是:
至此,基于端口的虚拟主机搭建的练习就完成了。
8.3、基于域名的虚拟主机
由于是测试使用,不采用网络域名测试(费米),这里采用windos静态映射文件的方式为虚拟机设置两个域名(如果在静态映射文件操作过程中遇到问题可以看Hadoop2.7小白级环境搭建教程文章中2.4.更改windows设置章节的详解)
在windows桌面的此电脑中打开以下路径的文件,通过记事本(打开方式随意)打开:
C:\Windows\System32\drivers\etc\hosts
按照以下格式将虚拟机IP 主机名 域名1 域名2 写入文件中的任意新行,保存退出即可:
192.168.70.155 node0 www.muxi.com www.keqi.com
与8.2节一样,通过快照将虚拟机恢复到设置完Nginx开机自启的快照,至此,我们的准备工作就完成了,接下来开始更改配置文件即可,进入/usr/local/nginx/conf/目录,更改nginx.conf文件:
# 进入到Nginx的配置为念目录
cd /usr/local/nginx/conf/
# 修改Nginx配置文件
vim nginx.conf
首先,为了测试明显,将keepalive_timeout设置为0:
将http块中的server块复制一份紧跟在原有server块之后:
接下来修改两个基于域名的主机会进入到不同的界面,用server_name指定不同虚拟主机的域名,location块中的root对应不同域名跳转的页面:
参考前面的测试案例,将Nginx目录下的html目录复制两份改名为muxi和keqi,再修改index中的内容就完成了不同页面的准备,如下图:
将文件内容更改为以下内容:
keqi目录的内容修改如下:
重启Nginx:
systemctl restart nginx
打开浏览器,在地址栏中输入www.muxi.com,结果如下:
打开浏览器,在地址栏中输入www.keqi.com,结果如下:
至此,基于域名的虚拟主机练习完成。
9、配置服务的反向代理
概述:Nginx服务的反向代理是一种服务器配置方式,其中Nginx服务器接收客户端的请求,然后将这些请求转发给后端服务器,最后将后端服务器的响应返回给客户端。在Nginx中通常使用proxy_pass实现反向代理。
学习此部分前需要提前下载好以下文件:
tomcat压缩包和jdk压缩包https://pan.baidu.com/s/1F-ZS17NN_9Om0ESe0yu3EQ?pwd=3nps参考下面文章的2.1-2.4章节搭建一个虚拟机node1,这里我的node1ip为192.168.70.156,为node1配置tomcat,完成tomcat配置后会将tomcat再复制一份,node1的两个tomcat用于模拟两台真实的服务器,node0用于反向代理node0的两个tomcat。
案例介绍:为虚拟主机node1安装两个Tomcat服务,通过nginx反向代理,本案例中使用两台虚拟机演示。Nginx安装在192.168.70.155环境中(也就是虚拟主机node0),Tomcat安装到192.168.70.156环境中(上面要求准备好的虚拟主机node1),为了避免端口冲突,两个tomcat分别使用端口8080与9090。
首先启动准备好的node1,进入/opt目录,新建apps目录用于存放jdk和tomcat包:
将前面下载好的tomcat和jdk文件拖拽进来,如果拖拽一直没有进度,说明缺少支持拖拽的插件,通过如下命令安装支持拖拽文件的插件:
yum -y install lrzsz
安装完插件后再依次拖入两个文件就能正常拖入了:
通过如下命令安装jdk:
rpm -ivh jdk-8u221-linux-x64.rpm
通过如下命令验证jdk是否安装成功:
java -version
接下来开始配置JDK环境变量,通过如下命令进入配置文件并添加JDK环境变量:
# 修改配置文件
vim /etc/profile
# 在文件末尾添加如下两行
export JAVA_HOME=/usr/java/default
export PATH=$PATH:$JAVA_HOME/bin
配置完成后,通过如下命令对刚才修改的配置文件生效:
source /etc/profile
通过如下命令测试配置文件是否生效:
jps
存在jps进程就说明配置文件生效了。
接下来通过如下命令解压/opt/apps目录下的tomcat压缩包,将解压后的文件存放在/opt目录下:
tar -zxvf apache-tomcat-8.5.61.tar.gz -C /opt/
进入/opt目录,将解压后的tomcat包重命名为tomcat1(因为node需要装两台tomcat,为了区分两台tomcat,故将解压后的tomcat改名为tomcat1,其实名字是什么不重要,只要能区分就行)
接下来我们启动测试一下tomcat,查看是否能正常运行:
# 进入tomcat启动脚本的目录
cd tomcat1/bin
# 启动tomcat
./startup.sh
进入浏览器在地址栏输入192.168.70.156:8080显示如下界面说明tomcat启动成功(注意:要将IP写为自己配置tomcat的虚拟主机IP才能请求成功):
为了后期测试两台tomcat的界面一目了然,我们将对tomcat的界面进行修改:
主要是修改body标签里的内容,只留一个h1标签即可:
保存文件退出后进入浏览器输入192.168.70.156:8080后显示如下界面:
测试完tomcat并修改了页面内容后,我们需要关闭tomcat:
关闭tomcat完成后,回到/opt目录下,将tomcat1复制一份改名为tomcat2:
为了区分两个tomcat的界面,修改tomcat2中的jsp文件:
[root@node1 opt]# vim tomcat2/webapps/ROOT/index.jsp
将body标签中h1标签的8080改为9090即可:
虽然我们的tomcat2在界面上与tomcat1存在了区别,但tomcat2测试时还是需要通过默认的8080端口才能访问,因此还需要更改tomcat2的请求端口,tomcat的端口修改在tomcat/conf目录下的server.xml文件中:
进入文件后,将port="8005"改为port="9095":
文件继续往下走还能看到一个port="8080",修改为port="9090"即可保存退出文件:
启动tomcat2:
进入浏览器在地址栏输入192.168.70.156:9090即可显示如下内容:
至此,node1中的两个tomcat就准备好了,接下来开始配置Nginx反向代理,首先启动装有Nginx的虚拟主机node0,修改nginx.conf配置文件:
首先将keepalive_timeout设置为0:
在http块中,通过upstream分别保存tomcat1和tomcat2的IP和端口,便于后面location块拿到目标IP和端口做反向代理:
upstream tomcat.server1{
server 192.168.70.156:8080;
}
upstream tomcat.server2{
server 192.168.70.156:9090;
}
在http块中的server块中,通过server_name指定访问tomcat1的域名为www.tomcat1.com:
server_name www.tomcat1.com;
将server块中的location块的root改为proxy_pass表示代理,后面跟http://前面保存tomcat1IP和端口的名字:
proxy_pass http://tomcat.server1;
至此,tomcat1的反向代理设置就完成了,将server块复制一份放在原有server块的后面,接下来开始修改新复制的server块内容,首先修改server_name对应的域名为www.tomcat.com(域名随意定):
server_name www.tomcat2.com;
由于操作重复,下面直接给出修改后的整个nginx.conf配置文件内容方便对照:
#user nobody;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
#tcp_nopush on;
keepalive_timeout 0;
#keepalive_timeout 65;
# 这里保存了tomcat1的IP和端口,server块中的location块会调用此处的信息
upstream tomcat.server1{
server 192.168.70.156:8080;
}
# 这里保存了tomcat2的IP和端口,server块中的第二个location块会调用此处的信息
upstream tomcat.server2{
server 192.168.70.156:9090;
}
gzip on;
server {
listen 80;
server_name www.tomcat1.com;
location / {
# 这里要将root改为proxy_pass表示代理
# proxy_pass后的域名来自于我们前面定义的tomcat.server1,它保存了tomcat1的IP和域名
proxy_pass http://tomcat.server1;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 80;
server_name www.tomcat2.com;
location / {
# 这里要将root改为proxy_pass表示代理
# proxy_pass后的域名来自于我们前面定义的tomcat.server2,它保存了tomcat2的IP和域名
proxy_pass http://tomcat.server2;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
由于我们在nginx.conf配置文件中为两个tomcat设置了不同的访问域名,因此需要通过windows的hosts文件为node0加入这两个域名:
# 打开windows的如下文件
C:\Windows\System32\drivers\etc\hosts
# 加入如下内容(注意修改为自己主机的ip)
192.168.70.155 node0 www.tomcat1.com www.tomcat2.com
更改完host文件的内容后,重启虚拟主机node0的Nginx:
systemctl restart nginx
打开node1中的两台tomcat:
# 开启tomcat1
cd /opt/tomcat1/bin
./starup.sh
# 开启tomcat2
cd /opt/tomcat2/bin
./starup.sh
进入浏览器,在地址栏输入我们为tomcat1设置的域名www.tomcat1.com,显示如下界面:
在地址栏输入我们为tomcat2设置的域名www.tomcat2.com,显示如下界面:
至此,配置服务反向代理的整个实验过程就圆满结束了!
10、负载均衡
概念:负载均衡是高可用网络基础架构的关键组件,通常用于将工作负载分布到多个服务器来提高网站、应用、数据库或其他服务的性能和可靠性。对于 Web 工程中的负载均衡,就是将相同的 Web 应用部署到多个不同的 Web 服务器上,形成多个 Web 应用服务器。当请求到来时,由负载均衡服务器负责将请求按照事先设定好的比例向 Web 应用服务器进行分发,从而增加系统的整体吞吐量。
10.1、Nginx负载均衡策略
10.1.1、轮询
这是Nginx默认的负载均衡策略,每个请求按时间的先后顺序逐一分配到不同的后端服务器,如果后端服务器宕机,能自动剔除宕机的服务器并在正常工作的服务器中做轮询。
10.1.2、指定权重
可以理解为更高级的轮询,通过指定不同服务器轮询的概率实现,weight默认为1,weight设置得越大访问比率就越高,这种负载均衡策略一般用于后端服务器性能不均的情况。
# 演示案例
upstream myServer {
# 这里没有指定weight的大小,默认weight=1
server 192.168.70.156;
server 192.168.70.157 weight=2;
server 192.168.70.158 weight=3;
}
10.1.3、IP绑定 ip_hash
每个请求按访问ip的hash结果分配,每个访客固定访问一个后端服务器,可以解决session的问题。例如:客户端A向反向代理服务器发送请求,代理服务器将请求发送给服务器A处理客户端A的请求,如果客户端A又向反向代理服务器发送了一个请求,由于客户端的IP没有改变,所以代理服务器还是会将客户端A的请求发送给之前处理过客户端A请求的服务器去处理。
# 演示案例
upstream myServer {
# 该方式主要是通过ip_hash声明的
ip_hash;
server 192.168.70.156;
server 192.168.70.157;
}
10.2、负载均衡实操
实验要求:集群包含一台 Nginx 服务器,两个 Web服务器(在第9章服务的反向代理章节中已经为node1配置了tomcat1和tomcat2,启动这两个tomcat模拟两个Web服务器)。
本章节实操在第9章实操的基础上进行,首先启动虚拟主机node0,进入/usr/local/nginx目录,修改配置文件内容:
# 进入node0的Nginx目录
cd /usr/local/nginx
# 修改配置文件
vim conf/nginx.conf
对于之前的配置我们不做删除,只做添加和修改,首先通过upstream分别指定两个服务器的权重:
# 8080端口采用默认权重,9090端口的权重设置为2
upstream rss{
server 192.168.70.156:8080;
server 192.168.70.156:9090 weight=2;
}
http块中的server块只保留一个,保留的server块中的server_name指定我们之前使用过的域名www.muxi.com:
server_name www.muxi.com;
将location块中proxy_pass代理的域名更新为http://rss,这里的rss时对应设置权重的upstream的命名,并不是固定的(就像是函数调用,函数名是什么不重要,重要的是要和你调用的函数名相同):
proxy_pass http://rss
完整的nginx.server配置文件如下:
#user nobody;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
#tcp_nopush on;
keepalive_timeout 0;
#keepalive_timeout 65;
# 这里保存了tomcat1的IP和端口,server块中的location块会调用此处的信息
upstream tomcat.server1{
server 192.168.70.156:8080;
}
# 这里保存了tomcat2的IP和端口,server块中的第二个location块会调用此处的信息
upstream tomcat.server2{
server 192.168.70.156:9090;
}
# 用于负载均衡练习设置权重
upstream rss{
server 192.168.70.156:8080;
server 192.168.70.156:9090 weight=2;
}
gzip on;
server {
listen 80;
server_name www.muxi.com;
location / {
# 这里要将root改为proxy_pass表示代理
# proxy_pass后的域名来自于我们前面定义的upstream设置权重的命名
proxy_pass http://rss;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
通过如下命令重启nginx使配置文件的更改生效:
systemctl restart nginx
参考第9章中打开windows的hosts文件为192.168.70.155添加www.muxi.com的域名并打开虚拟主机node1的两台tomcat。
打开浏览器,输入www.muxi.com,连续刷新会发现遵循以下截图的顺序循环出现:
至此,通过指定权重的负载均衡实操就完成了。
11、Location配置
提示:在之前学习的章节中有提到http块中的每个server就相当于一台主机,而Location就是server中包含的配置信息,用于定义服务器上不同uri路径的配置。
语法:
location [ = | ~ | ~* | ^~ ] uri { ... }
1、语法中uri前面的大括号中的"=","~","~*","^~"对应四种匹配方式,如果都不存在就采用默认的最大前缀匹配。
2、~和~*都表示正则匹配,区别在于~区分大小写,~*不区分大小写;
3、^~表示不使用正则匹配。
知识点补充:url = 协议://域名/uri
11.1、Location匹配方式
上面的location语法是用于匹配url中的uri(从前往后进行匹配),本质是当location指定的uri能够完全匹配请求的uri时,就会执行匹配的location配置;如果多个location指定的uri对请求的uri从前到后进行匹配只能匹配请求的部分uri,执行匹配uri最长的location配置;如果有不同匹配方式的location匹配相同长度的uri,就需要考虑到不同匹配方式的优先级问题。接下来通过下面的例子方便理解:
#以下用于模拟Nginx的Location配置
# 被请求的域名是www.muxi.com
# 下面是Location语法中拆分出来的例子,用于理解它们之间的匹配方式和优先级
# 例1:精确匹配
location = / {
[ 配置A ]
}
# 例2:最大前缀匹配
location / {
[ 配置B ]
}
# 例3:这个也是最大前缀匹配,只是不单单匹配根目录
location /doc/ {
[ 配置C ]
}
# 例4:采用^~修饰符匹配(不采用正则匹配),如果被^~修饰符匹配将不考虑正则匹配
location ^~ /img/ {
[ 配置D ]
}
# 例5:正则匹配
location ~* \.(gif|jpg|webp)$ {
[ 配置E ]
}
结合上面的Location配置,下面是Nginx收到的对www.muxi.com的请求,请说明这些请求的uri分别是通过哪个配置去匹配资源的:
请求1:"/"
答:Nginx收到的请求是"/",通过观察上面的Location配置可知,例1和例2都能匹配"/",但是一个请求不可能既执行配置A又执行配置2,但例1和例2都完全匹配,这就需要考虑到不同匹配方式的优先级问题,精确匹配的优先级大于最大前缀匹配,因此,在上述Location配置中,请求"/"会执行配置A。
请求2:"/index.html"
答:在请求2的请求中,例1是无法匹配的,正如例1匹配方式的名字:精确匹配(这种匹配方式需要与匹配项完全相同才会匹配),而例2是能够匹配的,因为例2的"/"与请求2的"/index.html"从最往后顺序匹配时,例2的"/"与请求2前面的"/"相匹配,而例3和例4与请求2从前往后依次匹配时都无法与自身uri相匹配,例5也无法匹配到自身不存在的.html后缀,因此,请求"index.html"会执行配置B。
请求3:"/doc/index.html"
答:首先排除例1,因为例1的"/"与"/doc/index.html"不完全匹配,例2的"/"与"/doc/index.html"从前到后进行匹配能匹配到例2的"/",例3的"/doc/"与"/doc/index.html"从前到后匹配能匹配到例3的"/doc",例4的"/img"与"/doc/index.html"从前到后匹配发现不能匹配到例4的"/img"匹配,所以例4直接pass,例5的正则匹配无法匹配到请求中".html"的后缀,所以例5也pass。我们发现,在上面的Location配置中只有例2与例3能够匹配,只有多个最大前缀匹配能够匹配请求uri时,选择匹配长度最长的匹配项,因此,请求3执行配置C。
请求4:"/img/hello.jpg"
答:首先排除例1,因为例1的"/"无法与请求4的"/img/hello.jpg"完全匹配,例2的"/"与请求4的"/img/hello.jpg"从前到后依次匹配时能够匹配到"/",例3的"/doc/"与请求4的"/img/hello.jpg"从前到后依次匹配时无法匹配到location指定的"/doc",因此例3pass,例4的"/img/"与请求4的"/img/hello.jpg"从前到后依次匹配时能够匹配到location指定的"/img/",例5通过正则表达式能够匹配到location指定的后缀".jpg",至此,例2,例4和例5都能匹配到请求4的"/img/hello.jpg"的部分uri,首先对比例2和例4,例4的匹配长度大于例2,因此例2pass,并且如果location指定的uri被"^~"修饰符修饰且与请求的uri相匹配,将不考虑正则匹配。(即有不使用正则匹配与请求相匹配时则不考虑正则匹配)因此,请求4执行配置D。
请求5:"/doc/hello.jpg"
答:首先排除例1,因为例1的"/"无法与请求5的"/doc/hello.jpg"完全匹配,例2的"/"与请求5的"/doc/hello.jpg"从前到后依次匹配时能够匹配到location指定的"/",例3的"/doc/"与请求4的"/doc/hello.jpg"从前到后依次匹配时能够匹配到location指定的"/doc",例4的"/img/"与请求4的"/doc/hello.jpg"从前到后依次匹配时不能匹配到location指定的"/img/",例5通过正则表达式能够匹配到location指定的后缀".jpg",至此,例2,例3和例5都能匹配到请求4的"/doc/hello.jpg"的部分uri,首先对比例2和例3,例3的匹配长度大于例2,因此例2pass,并且正则匹配的优先级高于最大前缀匹配的优先级,因此,请求5执行配置E。
优先级总结:
当匹配内容都相同的情况下,不同匹配方式存在以下大小关系:
精确匹配>不使用正则匹配>正则匹配>最大前缀匹配
11.2、Location的匹配顺序
多个精确匹配和最大前缀匹配在匹配请求的uri时都遵循"最大前缀"原则(即哪个location匹配的内容多就执行哪个location的配置),与前后顺序无关;而多个正则匹配在匹配时遵循"顺序匹配"原则(即按前后顺序进行匹配,匹配到第一个location就停止对后面其他使用正则匹配的location)。
当一个server中同时有精确匹配location,最大前缀匹配location和正则匹配location,在匹配请求的uri时会先对精确匹配location和最大前缀匹配location进行匹配,再考虑是否进行正则匹配(主要看是否存在不使用正则匹配("^~")的location,如果存在^~的匹配方式就不考虑正则匹配,反之就会进行正则匹配)
知识点补充:
1、客户端发来的请求格式为:请求头(域名/IP/端口号)+uri
2、请求头的内容决定了由哪个server块来处理,uri决定了执行server块中的哪个location配置。
特别注意:反向代理通过proxy_pass指定ip:port[uri]
11.3、Location实操
需求1:在地址栏输入www.muxi.com/aabb/进入tomcat8080的index.html和tomcat8080下指定的abcabc界面。
(本实操在负载均衡配置文件的基础上修改)打开装有Nginx的虚拟主机node0:
vim /usr/local/nginx/conf/nginx.conf
在server中添加如下内容:
location /abcabc {
proxy_pass http://192.168.70.156:8080/;
}
保存退出后重启Nginx:
systemctl restart nginx
打开装有tomcat的虚拟主机node1,启动tomcat:
cd /opt/tomcat1/bin
./startup.sh
进入浏览器,在地址栏输入http://www.muxi.com/abcabc会出现如下界面:
在配置文件中虽然配置了请求uri"/abcabc"的预期转发地址为http://192.168.70.156:8080/abcabc,但实际进入的却是192.168.70.156:8080,而不是预期地进入192.168.70.156:8080/abcabc,这其实是由于配置转发的地址后面加了"/",跳转到192.168.70.156:8080/abcabc的实现如下(方便对照,只是location配置中地址的区别):
vim /usr/local/nginx/conf/nginx.conf
将上面新加的location的转发地址端口号后面的"/"删掉保存即可:
重启nginx:
systemctl restart nginx
进入浏览器,在地址栏输入http://www.muxi.com/abcabc会出现如下界面:
出现404并不是我们的配置存在错误,而是因为我们偷了懒没有做界面的设置。
这个案例说明proxy_pass端口号后如果加了"/"无论请求的uri包含多少路径,都会默认去proxy_pass指定的页面,如果proxy_pass端口号后面没有加"/",uri会默认添加到访问页面的域名后,显示uri指定的页面,如果页面不存在就会报404。
需求二:在以上配置文件的基础上继续添加需求,在浏览器地址栏访问http://www.muxi.com/baidu能跳转到baidu.com官网。
任务1:实现跳转到百度页面后,之后的操作与http://www.muxi.com/无关
vim /usr/local/nginx/conf/nginx.conf
在server中加入如下location:
location /Baidu {
proxy_pass http://baidu.com/;
}
重启nginx:
systemctl restart nginx
当我们在浏览器的地址栏中输入http://www.muxi.com/baidu,出现如下界面:
观察地址栏,只剩下baidu.com,而不存在www.muxi.com,说明通过以上跳转操作后之后的操作已经与我们的nginx无关。
任务2:实现跳转到百度页面后所有的操作都与http://www.muxi.com/有关联且能正常使用百度搜索
vim /usr/local/nginx/conf/nginx.conf
修改刚才添加的location:
location /Baidu {
proxy_pass https://baidu.com/;
}
重启nginx:
systemctl restart nginx
当我们在浏览器的地址栏中输入http://www.muxi.com/baidu,出现如下界面(如果地址没有正确显示可以尝试清除浏览器缓存):
通过观察地址栏,虽然跳转到了baidu页面,但后期的操作还是与www.muxi.com有关联。
但是我们在地址栏中输入任意内容进行搜索时都会报404的错误,此时我们观察地址栏,域名后跟着s?加上各种字符,我们需要为server添加正则匹配使百度搜索能够正常运行。
vim /usr/local/nginx/conf/nginx.conf
在我们上面添加的location后继续添加正则匹配的location用于uri的扩展:
location ~*/s.* {
# 域名后一定不要跟"/",让正则匹配的内容自动添加到域名后实现页面跳转
proxy_pass https://www.baidu.com;
}
防止迷路,这里给出目前的nginx.server配置内容:
#user nobody;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
#tcp_nopush on;
keepalive_timeout 0;
#keepalive_timeout 65;
# 这里保存了tomcat1的IP和端口,server块中的location块会调用此处的信息
upstream tomcat.server1{
server 192.168.70.156:8080;
}
# 这里保存了tomcat2的IP和端口,server块中的第二个location块会调用此处的信息
upstream tomcat.server2{
server 192.168.70.156:9090;
}
# 用于负载均衡练习设置权重
upstream rss{
server 192.168.70.156:8080;
server 192.168.70.156:9090 weight=2;
}
gzip on;
server {
listen 80;
server_name www.muxi.com;
location / {
# 这里要将root改为proxy_pass表示代理
# proxy_pass后的域名来自于我们前面定义的upstream设置权重的命名
proxy_pass http://rss;
index index.html index.htm;
}
location /abcabc {
proxy_pass http://192.168.70.156:8080;
}
location /baidu {
proxy_pass https://www.baidu.com/;
}
location ~*/s.* {
# 域名后一定不要跟"/",让正则匹配的内容自动添加到域名后实现页面跳转
proxy_pass https://www.baidu.com;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
重启nginx:
systemctl restart nginx
在浏览器的地址栏中输入http://www.muxi.com/baidu,并搜索nginx学习记录显示如下界面:
至此,利用location实现页面跳转并能关联百度的操作就完成了。
12、配置动静分离
12.1、动静分离概述
概述:Nginx动静分离就是将动态请求和静态请求分开,可以理解成使用Nginx处理静态请求,Tomcat等服务器处理动态请求。
动静分离的两种实现方式:
①为静态文件设置单独的域名,放在独立的服务器上(主流方案)。
②将动态和静态文件混合在一起发布,通过Nginx的location指定不同的文件实现不同的请求转发(对后期升级维护不友好)。
12.2、实操理解
12.2.1、实操准备
接下来通过实操来理解动静分离,需要准备两个tomcat和两个Nginx:
启动装有tomcat的主机node1,修改tomcat1和tomcat2首页的内容:
# 修改tomcat1的首页内容
vim /opt/tomcat1/webapps/ROOT/index.jsp
-----------------------------------------------------------------
# 清空文件原有内容,将以下内容写入tomcat1的index.jsp (注意替换ip)
<link rel="stylesheet" type="text/css" href="/css/index.css">
<img src="/image/img.png"><br/>
<p>from 192.168.70.156:8080</p>
-----------------------------------------------------------------
# 修改tomcat2的首页内容
vim /opt/tomcat2/webapps/ROOT/index.jsp
-----------------------------------------------------------------
# 清空文件原有内容,将以下内容写入tomcat2的index.jsp (注意替换ip)
<link rel="stylesheet" type="text/css" href="/css/index.css">
<img src="/image/img.png"><br/>
<p>from 192.168.70.156:9090</p>
接下来准备两个Nginx,首先将装有Nginx的主机node0关机,为node0拍摄快照取名为动静分离前,然后通过node克隆一台主机取名为node2,ip设置为192.168.70.157,如果存在疑问可通过下面文章的第四章,文章的第四章手把手教你克隆后ip修改,主机名修改,连接xshell等操作:
Hadoop2.7小白级环境搭建教程_windows hadoop 2.7-CSDN博客文章浏览阅读459次。输入完上面的指令后回车即会显示如下界面,代表我们已经打开了网络配置文件,单击键盘i键即可进行编辑,大家可以参考我的文件,主要是修改了上部分的BOOTPROTO="static",并且插入了最后三行语句,修改完成后,我们需要先按键盘左上角的ESC键,然后输入:wq即可将文件保存并退出文件(这里小白需要注意的是按完ESC键后一定要先按键盘的"Shift "加 ":"键将冒号输出来,才能输入wq完成上面所说的操作)_windows hadoop 2.7https://blog.csdn.net/qq_62714412/article/details/133162412创建完虚拟主机node2后建议为node2拍摄快照,方便恢复现状进行各种操作。
打开node2进行如下操作:
# 创建文件夹用于存放文件
mkdir -p /data/image /data/css
进入node2的/data/image目录,拖入任意一个图片进去即可(拖入前记得改名为img.png,与tomcat中调用的图片名一致即可)
进入到node2的/data/css目录,创建名为index.css文件并写入以下内容:
# index.css文件的内容
p{color:rgb(248, 171, 171);font-size:80px}
至此,我们准备了两个tomcat和两个Nginx,其中,两台tomcat用于处理动态请求,node0的Nginx用于服务器代理,node2的Nginx用于处理静态请求。
12.2.2、动静分离实操
(以下实操记得将IP修改为自己虚拟主机对应的IP)首先修改node2的Nginx配置文件:
vim /usr/local/nginx/conf/nginx.conf
将server_name指定的内容修改为node2的IP即192.168.70.157:
server_name 192.168.70.157;
由于对location的改动较大(只涉及server内的修改),在此直接给出nginx.conf文件内容:
#user nobody;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
#tcp_nopush on;
keepalive_timeout 0;
#keepalive_timeout 65;
# 这里保存了tomcat1的IP和端口,server块中的location块会调用此处的信息
upstream tomcat.server1{
server 192.168.70.156:8080;
}
# 这里保存了tomcat2的IP和端口,server块中的第二个location块会调用此处的信息
upstream tomcat.server2{
server 192.168.70.156:9090;
}
# 用于负载均衡练习设置权重
upstream rss{
server 192.168.70.156:8080;
server 192.168.70.156:9090 weight=2;
}
gzip on;
server {
listen 80;
server_name 192.168.70.157;
location /image {
# 由于访问Nginx时是获取自身的资源文件,不涉及请求转发,因此这里用到root
root /data;
}
location /css {
root /data;
}
}
}
重启node2的Nginx:
systemctl restart nginx
测试一下node2的配置内容是否有错,在地址栏输入192.168.70.157/image/img.png得到下图:
在地址栏输入192.168.70.157/css/index.css得到我们在主机node2的index.css文件中写入的内容:
接下来修改node0上的nginx.conf文件:
vim /usr/local/nginx/conf/nginx.conf
主要修改server块内的location:
#user nobody;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
#tcp_nopush on;
keepalive_timeout 0;
#keepalive_timeout 65;
# 这里保存了tomcat1的IP和端口,server块中的location块会调用此处的信息
upstream tomcat.server1{
server 192.168.70.156:8080;
}
# 这里保存了tomcat2的IP和端口,server块中的第二个location块会调用此处的信息
upstream tomcat.server2{
server 192.168.70.156:9090;
}
# 用于负载均衡练习设置权重
upstream rss{
server 192.168.70.156:8080;
server 192.168.70.156:9090 weight=2;
}
gzip on;
server {
listen 80;
server_name www.muxi.com;
location / {
proxy_pass http://rss;
}
location /image/ {
# 注意ip后不要加"/",否则无法进入到node2的"/image"目录
proxy_pass http://192.168.70.157;
}
location /css/ {
# 注意ip后不要加"/",否则无法进入到node2的"/css"目录
proxy_pass http://192.168.70.157;
}
}
}
重启node0的Nginx:
systemctl restart nginx
启动node的tomcat1和tomcat2:
进入浏览器输入www.muxi.com出现如下界面:
至此,动静分离的实验到此结束,下面给出总结实验的流程图:
13、动态负载均衡
13.1、什么是动态负载均衡
概述:在第十章中的负载均衡是通过upStream实现的,但是如果需要临时添加为Nignx添加服务就需要重启Nginx使nginx.conf配置文件内容生效,但是考虑到真实的使用场景如果频繁的重启服务非常影响用户体验,因此提出了动态负载均衡的概念,实现Upstream可配置化、动态化,无需人工重新加载nginx.conf,核心是通过注册中心监控和管理服务(注册中心存放IP地址和端口号,IP区分主机、port区别进程。)。
13.2、服务注册与发现框架Consul
常见服务发现框架 Consul、Eureka、 ZooKeeper、Etcd 。ZooKeeper是这种类型的项目中历史最悠久的之一,起源于Hadoop。非常成熟、可靠。
Consul是一款开源的分布式服务注册与发现系统,通过HTTP API可以使得服务注册、发现实现起来非常简单,它支持如下特性:
- 服务注册:服务实现者可以通过HTTP API或DNS方式,将服务注册到Consul。
- 服务发现:服务消费者可以通过HTTP API或DNS方式,从Consul获取服务的IP和PORT。
- 故障检测:支持如TCP、HTTP等方式的健康检查机制,从而当服务有故障时自动摘除。
- K/V存储:使用K/V存储实现动态配置中心,其使用HTTP长轮询实现变更触发和配置更改。
- 多数据中心:支持多数据中心,可以按照数据中心注册和发现服务,即支持只消费本地机房服务,使用多数据中心集群还可以避免单数据中心的单点故障。
- Raft算法:Consul使用Raft算法实现集群数据一致性。
13.3、Consul环境搭建
此次Consul环境搭建只搭建了ConsulServer,搭建完成后只能实现客户端对ConsulServer的访问。
打开虚拟主机node0,进入/opt/apps/目录,首先下载wget:
yum -y install wget
然后通过wget下载Consul压缩包:
wget https://releases.hashicorp.com/consul/0.7.5/consul_0.7.5_linux_amd64.zip
由于下载的压缩包后缀为.zip,因此需要通过unzip解压,首先下载unzip:
yum -y install unzip
解压Consul到当前目录:
unzip consul_0.7.5_linux_amd64.zip
将解压后的consul文件移动到/opt/目录下:
mv consul ../
进入/opt目录通过./consul验证Consul能否正常使用:
通过如下命令启动Consul (由于我们没有将consul放在/root/bin目录下,所以启动时需要在consul的安装目录启动):
# 记得将命令里的IP替换成安装了consul的虚拟主机IP
./consul agent -dev -ui -node=consul-dev -client=192.168.70.155
进入浏览器,在地址栏输入http://192.168.70.155:8500进入如下界面(端口号固定,替换IP即可):
对于将参数传递给Consul的业务推荐使用postmanhttps://www.postman.com/downloads/进行传参,传参地址需要写完整的地址,例如http://192.168.70.155:8500/ui/#/dc1/services ,传参格式要选择JSON格式传递。
13.4、Consul添加服务
①将发送方式改为post;
②将consul的地址填入地址栏,参考如下地址:
http://192.168.70.155:8500/v1/catalog/register
③选择Body;
④选择raw;
⑤选择JSON格式;
⑥添加JSON格式内容,参考内容如下:
# 不要修改Json文件中的键
{"Datacenter": "dc1","Node":"tomcat", "Address":"192.168.70.156","Service": {"Id" :"192.168.70.156:8080", "Service": "tomcat1","tags": ["dev"], "Port": 8080}}
# 将tomcat9090端口也注册进来
{"Datacenter": "dc1","Node":"tomcat", "Address":"192.168.70.156","Service": {"Id" :"192.168.70.156:9090", "Service": "tomcat2","tags": ["dev"], "Port": 9090}}
写完内容后点击Send向Consul发送数据,得到true的反馈就说明发送成功:
进入http://192.168.70.155:8500,选择NODES就能看到我们添加的服务,如下图:
13.5、nginx-upsync-module
概述:Upsync是新浪微博开源的基于Nginx实现动态配置的第三方模块。Nginx-Upsync-Module的功能是拉取Consul的后端server的列表,并动态更新Nginx的路由信息。此模块不依赖于任何第三方模块。Consul作为Nginx的DB,利用Consul的KV服务,每个Nginx Work进程独立的去拉取各个upstream的配置,并更新各自的路由。
作用:nginx动态获取最新upstream信息
提前下载:nginx-upsync-module压缩文件https://pan.baidu.com/s/1pWRCJ5RrrZWGhJaJ1mQE9g?pwd=cmi5
打开装有Nginx的虚拟主机node0,进入/opt/apps目录,将下载好的nginx-upsync-module压缩文件拖入目录中:
解压master.zip:
在/opt下新建一个名为upsync的文件夹,将解压的nginx-upsync-module-master目录移动到新建的upsync目录下:
13.6、Nginx重装
由于在之前的章节中为node0的Nginx设置了自启动,所以重装Nginx前需要禁用Nginx服务:
# 关闭nginx
systemctl stop nginx
# 关闭nginx自启动
systemctl disable nginx
添加用户和用户组nginx:
# 添加用户组
groupadd nginx
# 添加用户(要求:用户组指定为nginx,并且设置为伪用户)
useradd -g nginx -s /sbin/nologin nginx
删除之前在安装Nginx时创建的目录:
rm -fr /var/temp/nginx/
提前准备如下目录:
mkdir -p /var/temp/nginx/client
对之前安装在/usr/local目录下的nginx打包备份:
tar -zcvf nginx_backup_upsync_pre.tar.gz /usr/local/nginx/
删除备份过的nginx:
在/usr/local目录下新建一个nginx文件夹用于存放重装的Nginx:
第一次安装Nignx时在/opt/apps/目录下的nginx-1.24.0中做了配置,由于需要重装Nginx,配置不通用,直接删掉这一目录再重新解压一份即可:
生成Makefile文件并编译安装:
# 进入新解压到的nginx-1.24.0
cd nginx-1.24.0
------------------------------------
# 进行配置(与第一次安装Nginx的配置相比新增了用户组,用户和add-module)
./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_flv_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-http_realip_module \
--http-client-body-temp-path=/var/temp/nginx/client/ \
--http-proxy-temp-path=/var/temp/nginx/proxy/ \
--http-fastcgi-temp-path=/var/temp/nginx/fcgi/ \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
--http-scgi-temp-path=/var/temp/nginx/scgi \
--with-pcre \
--add-module=/opt/upsync/nginx-upsync-module-master
--------------------------------------------------------------------
#编译并安装
make&&make install
打开Nginx自启动并启动Nginx:
进入浏览器,在地址栏输入192.168.70.155验证Nginx是否重装成功:
至此,Nginx重装完成。
13.7、配置Nginx动态负载均衡
打开重装Nginx后的虚拟主机node0,进入配置文件nginx.conf:
vim /usr/local/nginx/conf/nginx.conf
完整配置内容如下:
#user nobody;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 0;
#keepalive_timeout 65;
#gzip on;
# 获取注册的真实反向代理地址
upstream Dynamic1{
#自己虚拟出的(作为监听用的) 端口号(固定死的)
server 127.0.0.1:11111;
#连接consul server动态获取upstream配置负载均衡信息
#读取的是myDynamic这个分组的!!!
upsync 192.168.70.155:8500/v1/kv/upstreams/myDynamic
upsync_timeout=6m
upsync_interval=500ms
upsync_type=consul
strong_dependency=off;
upsync_dump_path /usr/local/nginx/conf/servers/servers_test.conf
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://Dynamic1;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
动态负载均衡配置解析:
-
server 127.0.0.1:11111;
:指定一个固定的服务器(127.0.0.1:11111),作为此 upstream 块的监听器。 -
upsync 192.168.70.155:8500/v1/kv/upstreams/myDynamic;
:表示 Nginx 应该动态地从位于 192.168.70.155:8500 的 Consul 服务器获取 upstream 配置。它读取名为 "myDynamic" 的分组的配置信息。 -
upsync_timeout=6m;
:配置从 Consul 拉取上游服务器配置的超时时间为 6 分钟。 -
upsync_interval=500ms;
:配置从 Consul 拉取上游服务器配置的间隔时间为 500 毫秒。 -
upsync_type=consul;
:指定使用 Consul 作为配置服务器。 -
strong_dependency=off;
:强制依赖配置服务器的选项。此处设置为 "off" 表示如果配置服务器不可用,Nginx 仍然可以启动。 -
upsync_dump_path /usr/local/nginx/conf/servers/servers_test.conf;
:将从 Consul 服务器动态拉取的相关负载均衡配置信息持久化到指定文件路径(这里指定了/usr/local/nginx/conf/servers/servers_test.conf
)。
保存完文件后创建持久化负载均衡配置信息的目录:
mkdir /usr/local/nginx/conf/servers/
重启Nginx使配置文件生效:
systemctl restart nginx
13.8、测试动态负载均衡
首先启动node0的consul:
# 进入opt目录
cd /opt/
# 启动consul
./consul agent -dev -ui -node=consul-dev -client=192.168.70.155
打开psotman,向http://192.168.70.155:8500/v1/kv/upstreams/myDynamic/192.168.70.156:8080发送put请求:
同样的方式为9090端口也发送一个put请求:
启动node1的tomcat1和tomcat2:
打开浏览器在地址栏输入http://192.168.70.155:8500,点击上方的KEY/VALUE可以看到我们加入的两台tomcat:
浏览器新建一个窗口,在地址栏输入http://192.168.70.155/并不断刷新循环显示如下界面:
接下来为9090端口的主机添加配置,实现访问http://192.168.70.155/时不断刷新界面循环出现一次8080端口两次9090端口:
完成以上步骤后访问http://192.168.70.155/时不断刷新界面不会循环出现一次8080端口两次9090端口界面,通过不断的更换两个端口的权重发现了两个bug,①当主机a的权重为1,主机b的权重为2时只会显示主机b的界面;②当主机a与主机b的权重相同时不断刷新界面会发现主机a与主机b的界面相互交替,并没有按预想的权重出现;其他权重分配目前测试都是正常的。
填坑:通过后期的测试发现,需要将tomcat页面的内容修改后就能解决上述问题的bug①,由于页面中涉及到调用资源但我们没有做资源调度的location才导致页面显示错误。(页面内容修改参考本文16.3节的tomcat文件修改内容)
14、限流(只做了解)
概述:在程序开发时会预估负载,当系统暴露在公网中时,恶意攻击或正常突发流量等都可能导致系统被压垮,而限流就是保护措施之一。限流即控制流量,Nginx有两种限流设置,一是控制速率,二是控制并发连接数。
14.1、限流之限制速率
概述:ngx_http_limit_req_module 模块提供限制请求处理速率能力,使用了漏桶算法。下面的练习使用了 nginx limit_req_zone 和 limit_req 两个指令,用于限制单个IP的请求处理速率。
限流示例:
# 这里只演示关键代码
http {
limit_req_zone $binary_remote_addr zone=myRateLimit:10m rate=20r/s;
}
server {
location / {
limit_req zone=myRateLimit;
proxy_pass http://my_upstream;
}
}
演示代码解析:
http块中的"zone=myRateLimit:10m"表示一个大小为10M,名字为myRateLimit的内存区域,1M能存储16000个IP地址的访问信息。"$binary_remote_addr"用于存储客户端 IP 地址。"rate=20r/s"表示速率设置为每秒处理 20 次请求。
server中的"limit_req zone=myRateLimit;"表示根据先前在http块中定义的 myRateLimit 区域对指定IP强制执行速率限制。它将传入请求限制为指定的速率(每秒 20 次请求)。
但是上面的例子明显存在缺陷,如果正常流量突然增大,超出的请求将被拒绝,无法处理突发流量,此时可以结合 burst 参数使用来解决该问题(只需在以上代码的基础上为location做出修改):
server {
location / {
limit_req zone=myRateLimit burst=50 nodelay;
proxy_pass http://my_upstream;
}
}
演示代码解析:
burst=50:设置了允许的瞬时突发请求数。允许在超过速率限制时突发处理 50 个请求,这50个请求以队列的形式存在,但如果持续超过速率限制,仍会进行限制。
nodelay:针对的是 burst 参数,”burst=50 nodelay“ 表示这20个请求立马处理,不能延迟处理。但是,即使这50个突发请求立马处理结束,后续来了请求也不会立马处理。burst=50 相当于缓存队列中占了50个坑,即使请求被处理了,这50个位置这只能按 100ms一个来释放。
14.2、限流之限制连接数
概述:ngx_http_limit_conn_module 提供了限制连接数的能力,利用 limit_conn_zone 和 limit_conn 两个指令即可:
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
server {
...
limit_conn perip 10;
limit_conn preserver 100;
}
"limit_conn perip 10 "作用的key 是 $binary_remote_addr,表示限制单个IP同时最多能持有10个连接。
"limit_conn perserver 100" 作用的key是 $server_name,表示虚拟主机(server) 同时能处理并发连接的总数。
注意:只有当 request header 被后端server处理后,这个连接才进行计数。
---------------------------------------------------------------------------------------------------------------------------------
限流主要针对外部访问,内网访问相对安全,可以不做限流,通过设置白名单即可。利用 Nginx ngx_http_geo_module 和 ngx_http_map_module 两个工具模块即可:
在 nginx.conf 的 http 部分中配置白名单:
geo $limit {
default 1;
39.100.243.125 0;
192.168.0.0/24 0;
172.20.0.35 0;
}
map limit limit_key {
0 "";
1 $binary_remote_addr;
}
limit_req_zone $limit_key zone=myRateLimit:10m rate=10r/s;
代码解析:
geo 对于白名单(子网或IP都可以) 将返回0,其他IP将返回1。
map 将limit转换为 limit_key,如果是 $limit 是0(白名单),则返回空字符串;如果是1,则返回客户端实际IP。
limit_req_zone 限流的key不再使用 binary_remote_addr,而是limit_key 来动态获取值。如果是白名单,limit_req_zone 的限流key则为空字符串,将不会限流;若不是白名单,将会对客户端真实IP进行限流。
拓展;除限流外,ngx_http_core_module 还提供了限制数据传输速度的能力(即常说的下载速度)。
location /flv/ {
flv;
limit_rate_after 20m;
limit_rate 100k;
}
这个限制是针对每个请求的,表示客户端下载前20M时不限速,后续限制100kB/s。
15、Nginx原理
①.Nginx 在启动后,会有一个 master 进程和多个相互独立的 worker 进程。
②.Master接收来自外界的信号,向各worker进程发送信号,每个进程都有可能来处理这个连接。
③.Master进程能监控Worker进程的运行状态,当 worker 进程退出后(异常情况下),会自动启动新的 worker 进程。
当一个worker进程在accept()这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接,完成一个完整的请求。一个请求,完全由worker进程来处理,而且只能在一个worker进程中处理。
问题一:为什么使用进程不使用线程?
答:
1、节省锁带来的开销。每个worker进程都是独立的进程,不共享资源,不需要加锁。同时在编程以及问题查找时,也会方便很多。
2、独立进程,减少风险。采用独立的进程,可以让互相之间不会影响,一个进程退出后,其它进程还在工作,服务不会中断,master进程则很快重新启动新的worker进程。当然,worker进程的也能发生意外退出。
问题二: 如何处理并发请求?
答:每进来一个request,会有一个worker进程去处理。但不是全程的处理,处理到可能发生阻塞的地方,比如向上游(后端)服务器转发request,并等待请求返回。那么,这个处理的worker不会这么傻等着,他会在发送完请求后,注册一个事件:“如果upstream返回了,告诉我一声,我再接着干”。于是他就休息去了。此时,如果再有request 进来,他就可以很快再按这种方式处理。而一旦上游服务器返回了,就会触发这个事件,worker才会来接手,这个request才会接着往下走。由于web server的工作性质决定了每个request的大部份生命都是在网络传输中,实际上花费在server机器上的时间片不多,这就是几个进程就能解决高并发的秘密所在。
16、Keepalived实现Nginx高可用
在之前搭建的Nginx布局如下,如果有tomcat宕机,另一台tomcat能够立马补上宕机的tomcat缺口,处理客户端的请求,但是这种布局的致命缺点是如果Nginx反向代理服务器宕机,整个服务都将不能运行,即单点故障。
为了避免这样的情况发生,于是提出Nginx高可用的方案,即为Nginx设置一个备用的Nginx反向代理服务器(注意:在Nginx高可用集群中Nginx为了反向代理服务器的透明性,通过网络协议虚拟出一个IP,Master占用虚拟的IP(如果Master宕机,会从其他Backup中选举新的Master),客户端会将请求发送到虚拟的IP处理):
16.1、keepalived概述
概述:keepalived是集群管理中保证集群高可用的服务软件。Keepalived的作用是检测服务器的状态,如果有一台服务器宕机,或工作出现故障,Keepalived将检测到,并将有故障的服务器从系统中剔除,同时使用其他服务器代替该服务器的工作,当服务器工作正常后Keepalived自动将服务器加入到服务器群中,这些工作全部自动完成,需要人工做的只是修复故障的服务器。
keepalived工作在TCP/IP协议栈的IP层,TCP层,及应用层,工作原理基于VRRP协议。
网络层:Keepalived会定期向服务器群中的服务器发送一个数据包(即常用的ping程序),如果发现某台服务的IP地址没有激活,Keepalived便报告这台服务器失效,并将它从服务器集群中剔除。
传输层:Keepalived以TCP端口的状态来决定服务器工作正常与否,如web server的服务端口一般是80,如果Keepalived检测到80端口没有启动,则Keepalived将把这台服务器从服务器集群中剔除。
应用层:只要针对应用上的一些探测方式,如URL的get请求,或者对nginx脚本检测等;可以根据用户自定义添加脚本针对特定的服务进行状态检测,当检测结果与用户设定不一致,则把这台服务器从服务器群中剔除。
16.2、VRRP协议
VRRP协议的工作原理:
1、VRRP虚拟路由冗余协议是一种容错的主备模式的协议,当网络设备发生故障时,可以不影响主机之间通信情况下进行设备切换,并且相对于客户端来说切换过程是透明的。
2、一个VRRP路由器有唯一的标识:VRID,范围为0—255。
3、同一台路由器可以加入多个备份组,在不同备份组中有不同的优先级,使得该路由器可以在一个备份组中作为主用路由器,在其他的备份组中作为备用路由器。
4、提供了两种安全认证措施:明文认证和IP头认证。
VRRP选举机制:
- 如果某台路由器的IP地址与虚拟路由器的IP地址一致,那么这台就会被选为主路由器。
- 如果虚拟IP拥有者宕机,优先级数值大的路由器会被选举出,优先级范围0~255。
- 如果优先级一样高,IP地址数值大的路由器会被选举出。
16.3、安装keepalived
首先修改主机node1中两台tomcat的内容:
# 修改tomcat1的内容
vim /opt/tomcat1/webapps/ROOT/index.jsp
# tomcat1中的内容
<p>from 192.168.70.156:8080 tomcat1 </p>
# 修改tomcat2的内容
vim /opt/tomcat2/webapps/ROOT/index.jsp
# tomcat2中的内容
<p>from 192.168.70.156:9090 tomcat2 </p>
接下来修改主机node0的nginx.conf文件:
# 修改nginx.conf文件
vim /usr/local/nginx/conf/nginx.conf
# 完整文件内容如下
#user nobody;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
#tcp_nopush on;
keepalive_timeout 0;
#keepalive_timeout 65;
upstream rss{
server 192.168.70.156:8080;
server 192.168.70.156:9090 weight=2;
}
# check_nginx.sh脚本执行时使用
server {
listen 80;
server_name localhost;
location / {
root html;
}
}
# 用于配置Nginx高可用
server {
listen 80;
# 192.168.70.200是虚拟的IP
server_name 192.168.70.200;
location / {
proxy_pass http://rss/;
}
}
}
将node0的nginx.conf配置文件发送给node2:
scp nginx.conf 192.168.70.157:`pwd`
# 输入完后先输入yes
# 再输入主机node2的密码
创建主机node0的配置文件中要求的check_nginx.sh
# 进入家目录
cd /home
# 创建并编辑文件
vim check_nginx.sh
# check_nginx.sh内容
#!/bin/bash
#通过访问check.html页面来检查nginx是否宕机
url="http://192.168.70.155/check.html"
code=`curl -s -o /dev/null -w %{http_code} $url`
#通过判断相应编码是否是200来确定nginx宕机
if [ $code -ne 200 ];then
sleep 1
code=`curl -s -o /dev/null -w %{http_code} $url`
if [ $code -ne 200 ];then
#确定nginx是宕机,关闭本机的keepalived
systemctl stop keepalived
fi
fi
为check_nginx.sh添加执行权限:
chmod +x check_nginx.sh
再将node0上创建好的check_nginx.sh文件发送给node2:
scp check_nginx.sh 192.168.70.157:`pwd`
#后面还要输入node2的密码
在node0上的/usr/local/nginx/html目录创建一个check.html,并将该文件拷贝到node2的指定目录:
vim /usr/local/nginx/html/check.html
# 在文件中写入任意内容保存退出即可
scp check.html 192.168.70.157:`pwd`
以防万一,重启Nginx:
systemctl restart nginx
通过如下命令检查脚本是否达到预期运行效果:
sh -x /home/check_nginx.sh
测试无误后为安装了Nginx的node0和node2安装keepalived:
yum -y install keepalived
16.4、配置keepalived
node0通过如下命令找到keepalived的下载位置:
find / -name keepalived.conf
配置node0的keepalived.conf文件:
! Configuration File for keepalived
global_defs {
# 配置接收邮件的邮箱地址,在backup切换成Master时,会向指定的邮箱发送邮件
# 配置时注意:一行一个邮箱
notification_email {
shiye@gmail.com
}
# 指定发件人的邮箱
notification_email_from 1505800458@qq.com
# 指定发件smtp服务器的IP地址
smtp_server 192.168.70.1
# 指定当前节点连接smtp服务器的超时时间
smtp_connect_timeout 10
# 运行keepalived机器的标识
router_id node0
}
# 手动定义一个检查机制
vrrp_script chk_nginx{
# 指定检查的脚本文件
script "/home/check_nginx.sh"
# 每隔2秒检查一次
interval 2
# 权重在原来的基础上-20
weight-20
}
vrrp_instance VI_1 {
# 这里的Master不代表当前实例一直为Master
state MASTER
# 表示实例绑定的网卡设备
interface ens33
# VRRP协议中提到的VRID(范围为0~255)
virtual_router_id 51
# 这里设置优先级大小
priority 100
# 检查的间隔(默认1秒)
advert_int 1
# 安全认证的设置
authentication {
# 指定认证方式(PASS | AH)
auth_type PASS
# 指定认证密码
auth_pass 1111
}
# 指定虚拟IP地址,又名VIP
virtual_ipaddress {
192.168.70.200
}
# 配置检查机制
track_script{
# 调用上面定义的检查机制
chk_nginx
}
}
将node0配置好的keepalived.conf文件以root的身份发送给node2:
scp /etc/keepalived/keepalived.conf root@192.168.70.157:/etc/keepalived/
node2收到node0发来的keepalived.conf文件后依然需要修改:
! Configuration File for keepalived
global_defs {
# 配置接收邮件的邮箱地址,在backup切换成Master时,会向指定的邮箱发送邮件
# 配置时注意:一行一个邮箱
notification_email {
muxi@nginx.com
}
# 指定发件人的邮箱
notification_email_from shiye@nginx.com
# 指定发件smtp服务器的IP地址
smtp_server 192.168.70.1
# 指定当前节点连接smtp服务器的超时时间
smtp_connect_timeout 30
# 运行keepalived机器的标识(修改)
router_id node2
}
# 手动定义一个检查机制
vrrp_script chk_nginx {
# 指定检查的脚本文件
script "/home/check_nginx.sh"
# 每隔2秒检查一次
interval 2
# 权重在原来的基础上-20
weight-20
}
vrrp_instance VI_1 {
# 这里的Master不代表当前实例一直为BACKUP(修改)
state BACKUP
# 表示实例绑定的网卡设备
interface ens33
# VRRP协议中提到的VRID(范围为0~255)(修改)
virtual_router_id 52
# 这里设置优先级大小(修改)
priority 90
# 检查的间隔(默认1秒)
advert_int 1
# 安全认证的设置
authentication {
# 指定认证方式(PASS | AH)
auth_type PASS
# 指定认证密码
auth_pass 1111
}
# 指定虚拟IP地址,又名VIP
virtual_ipaddress {
192.168.70.200
}
# 配置检查机制
track_script {
# 调用上面定义的检查机制
chk_nginx
}
}
16.5、Nginx高可用测试
启动node0的keepalived:
# 启动keepalived
systemctl start keepalived
# 查看keepalived启动状态
systemctl status keepalived
启动两台tomcat,然后进入浏览器地址栏输入192.168.70.200后循环显示如下界面:
测试完node0的keepalived,接下来测试node2的keepalived,重启node2的nginx并打开keepalived:
systemctl restart nginx
systemctl start keepalived
关闭node0主机的Nginx,再进入浏览器,在地址栏输入192.168.70.200循环出现如下界面:
至此,Nginx的学习到此结束。