目录

本文简介

本文主要介绍了Nginx的基本概念、应用场景、常用命令、Nginx的安装、常用命令以及配置文件、反向代理、负载均衡、动静分离、集群高可用以及Nginx的实现原理等等,同时通过手动测试进行理解,希望对来到这里的你有所帮助。【学习自B站尚硅谷Nginx视频】

一、Nginx的基本概念

1.1、Nginx是什么?

在百度百科中,它是这么介绍Nginx的,如下所示:

Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。
其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。2011年6月1日,nginx 1.0.4发布。
Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。

总的来说:

  • Nginx是一个高性能的Http和反向代理服务器
  • 占内存少,并发能力强,专门为性能优化而开发
  • 我们都知道性能是最重要的参考量,在实现上非常注重效率,Nginx它能够经受住高负载的考验,研究表明,最多能够支持5w个并发连接数

1.2、Nginx能帮助我们做些什么?

  • 正向代理
  • 反向代理
  • 动静分离
  • 负载均衡
  • 集群高可用

1.3、Nginx的特性

(1)Nginx作为HTTP服务器有以下几个特性:

  • 能够处理静态文件、索引文件以及自动索引;
  • 具有无缓冲的反向代理加速,还有简单的负载均衡以及集群容错;
  • 支持SSL和TLSSNI。

(2)Nginx专门为性能优化而开发,能够经受住高负载,研究表明高达5w个并发连接数;

(3)Nginx具有很高的稳定性。其它HTTP服务器,当遇到访问的峰值,或者有人恶意发起慢速连接时,也很可能会导致服务器物理内存耗尽频繁交换,失去响应,只能重启服务器。而Nginx采取了分阶段资源分配技术,使得它的CPU与内存占用率非常低。nginx官方表示保持10,000个没有活动的连接,它只占2.5M内存,所以类似DOS这样的攻击对nginx来说基本上是毫无用处的。

(4)Nginx支持热部署。它的启动特别容易, 并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还能够在不间断服务的情况下,对软件版本进行进行升级。

(5)Nginx采用master-slave(主从)模型,能够充分利用SMP的优势,且能够减少工作进程在磁盘I/O的阻塞延迟。当采用select()/poll()调用时,还可以限制每个进程的连接数。

(6)Nginx代码质量非常高,代码很规范,手法成熟, 模块扩展也很容易。

等等特性,详情可参考【Nginx是什么?Nginx介绍及Nginx的优点】,这篇文章,写得非常详细。

以上介绍的特性当中提到了Nginx的相关特性,接下来我们介绍一下关于Nginx一些特性的相关概念。

二、Nginx的安装

2.1、环境介绍

  • Linux的版本:Centos 7
  • Nginx的版本:最新版 nginx-1.19.4.tar.gz
  • Nginx的安装包下载地址:官网地址
    或者是使用命令下载安装包:wget http://nginx.org/download/nginx-1.19.4.tar.gz

2.2、安装Nginx

  • 首先我们需要安装包,这里我们可以使用文件上传工具,将文件上传到Linux中,如果不知道该怎么上传文件,请看【Linux文件上传介绍

  • 第一步:安装gcc。
    安装 nginx 需要先将官网下载的源码进行编译,编译依赖 gcc 环境,如果没有 gcc环境,需要安装 gcc,
    安装命令:yum install gcc-c++

  • 第二步:安装pcre。
    PCRE(Perl Compatible Regular Expressions)是一个 Perl 库,包括 perl 兼容的正则表达式库。nginx 的 http 模块使用 pcre 来解析正则表达式,所以需要在 linux 上安装 pcre 库。
    安装命令:yum install -y pcre pcre-devel
    :pcre-devel 是使用 pcre 开发的一个二次开发库。nginx 也需要此库。

  • 第三步:安装zlib库。
    zlib库提供了很多种压缩和解压缩的方式,nginx使用zlib对http包的内容进行gzip,所以需要在 linux 上安装 zlib 库。
    安装命令yum install -y zlib zlib-devel

  • 第四步:安装openssl库。
    (1)OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及 SSL 协议,并提供丰富的应用程序供测试或其它目的使用。
    (2)nginx 不仅支持 http 协议,还支持 https(即在 ssl 协议上传输 http),所以需要在linux 安装 openssl 库。
    安装命令:yum install -y openssl openssl-devel

注意:前面四步其实可以合成一步安装,命令为yum install -y gcc gcc-c++ make libtool wget pcre pcre-devel zlib zlib-devel openssl openssl-devel

  • 第五步:上传Nginx安装包,并解压、安装。
    按照以下步骤进行安装。
这里由于我安装了【yum install -y lrzsz】
并且Nginx的安装包不是很大,所以直接使用rz命令选择文件上传。
当然也可以使用命令:  wget http://nginx.org/download/nginx-1.19.4.tar.gz 进行云下载

我的解压目录在 /root/temp

# 1.文件解压
tar -zxvf nginx-1.19.4.tar.gz

# 2.创建临时文件的存放目录
cd /var
mkdir temp
cd temp
mkdir nginx

# 3.回到Nginx解压后的根目录下
cd /root/temp/nginx-1.19.4

# 4.进入到该目录之后可以看到configure这个可执行文件,配置安装参数+
# 5.参数设置如下所示,直接复制粘贴即可
./configure \
--prefix=/usr/local/nginx \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--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 \
--http-scgi-temp-path=/var/temp/nginx/scgi

# 6.之后我们回到解压后的Nginx的根目录下,使用gcc编译安装
make && make install

# 以上命令执行完以后,就会自动在/usr/local/nginx下创建一个目录,这个位置就是安装目录
# Nginx就是安装在这个位置

这样就可以将Nginx安装到linux中了。
特别要注意,安装Nginx之前先要将安装环境配置完成,不然安装Nginx会安装失败。

注意

  • 上边将临时文件目录指定为/var/temp/nginx,需要在/var 下创建 temp以及nginx目录;
  • nginx安装成功之后,默认安装在/usr/local目录下,关于启动和关闭nginx后文会介绍。

2.3、Docker安装运行Nginx

在此前,请学习我的文章学习Docker,看完这篇超详细的教程就足够了,熟悉Docker的基本命令以及操作。

  • Docker下安装运行Nginx的命令为:
待更新

三、Nginx的常用命令介绍

3.1、操作Nginx【Centos6和7通用】

1、查看版本号
/usr/local/nginx/sbin/nginx -v
在这里插入图片描述

2、启动 nginx
首先cd /usr/local/nginx/sbin/进入到nginx的安装目录下,
然后执行./nginx 命令进行启动Nginx。
启动之后使用命令:ps aux|grep nginx 查看是否启动
在这里插入图片描述

注意:执行./nginx 启动 nginx ,这里可以-c 指定加载的 nginx 配置文件,如下:
./nginx -c /usr/local/nginx/conf/nginx.conf

如果不指定-c ,nginx在启动时默认加载 conf/nginx.conf 文件,此文件的地址也可以在编译安装 nginx 时指定./configure 的参数(--conf-path= 指向配置文件(nginx.conf

3、停止 nginx

  • 方式 1,快速停止:
    首先进入cd /usr/local/nginx/sbin该目录下
    然后利用命令:./nginx -s stop进行关闭
    此方式相当于先查出 nginx 进程 id 再使用 kill 命令强制杀掉进程。

  • 方式 2,完整停止(建议使用):
    首先进入cd /usr/local/nginx/sbin该目录下
    然后利用命令:./nginx -s quit进行关闭,或者是使用./nginx -s stop
    此方式停止步骤是待 nginx 进程处理任务完毕进行停止。

4、重启 nginx

  • 方式 1,先停止再启动(建议使用):
    对 nginx 进行重启相当于先停止 nginx 再启动 nginx,即先执行停止命令再执行启动命令。如下:
    ./nginx -s quit
    ./nginx

  • 方式 2,重新加载配置文件:
    当 nginx 的配置文件 nginx.conf 修改后,要想让配置生效需要重启 nginx,使用-s reload
    不用先停止 nginx 再启动 nginx 即可将配置信息在 nginx 中生效,如下:
    ./nginx -s reload

5、测试
nginx 安装成功,启动 nginx,即可访问虚拟机上的 nginx
Nginx 默认的是侦听 80 端口
本机测试的IP地址是:192.168.15.131
在这里插入图片描述

注意:测试前需要将防火墙关闭【如果不熟悉命令的话,那么请看我之前的文章,Centos6.5的Linux命令介绍】【Centos 7版本的关闭防火墙命令为:systemctl stop firewalld】,如果是云服务器需要在安全组的配置中将80端口方行,不然80端口的访问会被阻拦。

3.2、命令总结

  • 查看Nginx版本:/usr/local/nginx/sbin/nginx -v
  • 普通启动服务:/usr/local/nginx/sbin/nginx
  • 配置文件启动:/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
  • 暴力停止服务:/usr/local/nginx/sbin/nginx -s stop
  • 优雅停止服务:/usr/local/nginx/sbin/nginx -s quit
  • 检查配置文件:/usr/local/nginx/sbin/nginx -t
  • 重新加载配置:/usr/local/nginx/sbin/nginx -s reload
  • 查看相关进程:ps -ef | grep nginx

四、Nginx的配置文件介绍

4.1、打开文件的方式介绍

Nginx的配置文件是非常重要的,文件的位置在安装目录的conf目录下,这里的位置/usr/local/nginx/conf目录下的一个叫nginx.conf的文件中。
我们在该目录下打开该文件:

# 进入到该目录下
cd /usr/local/nginx/conf/

# 打开配置文件,可以用EditPlus这个工具在windows中打开,也可以使用【vim + 文件名】 去查看
这里由于我使用的是EditPlus,所以就直接打开了【工具下载百度就有】。【步骤如下】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这样我们就可以在这里搞事情了,这个工具非常好用,可以的话我就将软件上传到我的资源当中,到时候大家有需要可以前去下载使用。下面我们开始看一下这个配置文件详细信息。

4.2、配置文件详解

我们打开nginx.conf这个文件可以发现,nginx.conf配置文件中的内容分为三个部分:

  • 全局块
  • events块
  • http块

下面我们逐一去了解。

4.2.1、第一部分:全局块

从配置文件开始到 events 块之间的内容,主要会设置一些影响 nginx 服务器整体运行的配置指令,主要包括配置运行 Nginx 服务器的用户(组)、允许生成的 worker process 数,进程 PID 存放路径、日志存放路径和类型以及配置文件的引入等。

  • 配置运行Nginx服务器用户(组)
  • worker process数
  • Nginx进程
  • PID存放路径错误日志的存放路径
  • 一个nginx进程打开的最多文件描述符数目
#配置worker进程运行用户(和用户组),nobody也是一个linux用户,一般用于启动程序,没有密码
#user  nobody;   

#配置工作进程数目,根据硬件调整,通常等于CPU数量或者2倍于CPU数量
worker_processes  1; # nginx支持的并发数

#配置全局错误日志及类型,[debug | info | notice | warn | error | crit],默认是error
error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#配置进程pid文件
pid        logs/nginx.pid;

#一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(系统的值ulimit -n)与nginx进程数相除,但是nginx分配请求并不均匀,所以建议与ulimit -n的值保持一致。
worker_rlimit_nofile 65535;

worker_processes 1;的意思是:Nginx 服务器并发处理服务的关键配置worker_processes 值越大,可以支持的并发处理量也越多,但是会受到硬件、软件等设备的制约,后文会介绍该数目配置多少合适。

4.2.2、第二部分:events 块

events 块涉及的指令主要影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 work process 下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个 word process 可以同时支持的最大连接数等。

  • 事件驱动模型的选择
  • 最大连接数的配置
events {
    #参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; 
    #epoll模型是Linux 2.6以上版本内核中的高性能网络I/O模型,如果跑在FreeBSD上面,就用kqueue模型。
    use epoll;

    worker_connections  1024; # 支持最大的连接数
}

例如上面给出的worker_connections 1024;表示每个 work process 支持的最大连接数为 1024,这部分的配置对 Nginx 的性能影响较大,在实际中应该灵活配置。

4.2.3、第三部分:http 块

这一部分是Nginx 服务器配置最频繁的部分,因为关于代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在这里进行。下面给出http块的配置。

http {
    include       mime.types; #文件扩展名与文件类型映射表
    default_type  application/octet-stream; #默认文件类型
	charset utf-8; #默认编码
	server_names_hash_bucket_size 128; #服务器名字的hash表大小
	client_header_buffer_size 32k; #上传文件大小限制
	large_client_header_buffers 4 64k; #设定请求缓冲
	client_max_body_size 8m; #设定请求缓冲
	sendfile on; #开启高效文件传输模式,对于普通应用设为on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。
	autoindex on; #开启目录列表访问,合适下载服务器,默认关闭。
	tcp_nopush on; #防止网络阻塞
	tcp_nodelay on; #防止网络阻塞
	keepalive_timeout 120; #长连接超时时间,单位是秒
	
	#FastCGI相关参数是为了改善网站的性能:减少资源占用,提高访问速度。
	fastcgi_connect_timeout 300;
	fastcgi_send_timeout 300;
	fastcgi_read_timeout 300;
	fastcgi_buffer_size 64k;
	fastcgi_buffers 4 64k;
	fastcgi_busy_buffers_size 128k;
	fastcgi_temp_file_write_size 128k;

    #gzip模块设置
	gzip on; #开启gzip压缩输出
	gzip_min_length 1k; #最小压缩文件大小
	gzip_buffers 4 16k; #压缩缓冲区
	gzip_http_version 1.0; #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
	gzip_comp_level 2; #压缩等级
	gzip_types text/plain application/x-javascript text/css application/xml; #压缩类型
	gzip_vary on; #增加响应头'Vary: Accept-Encoding'
	limit_zone crawler $binary_remote_addr 10m; #开启限制IP连接数的时候需要使用


    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;	
        location = /50x.html {
            root   html;
        }

	......
    }

}
.....

需要注意的是:http 块也可以包括 http 全局块server 块

①、http全局块

http 全局块配置的指令包括:

  • 定义MIMI-Type
  • 自定义服务日志
  • 允许sendfile方式传输文件
  • 连接超时时间
  • 单连接请求数上限
    include       mime.types; #文件扩展名与文件类型映射表
    default_type  application/octet-stream; #默认文件类型
	charset utf-8; #默认编码
	server_names_hash_bucket_size 128; #服务器名字的hash表大小
	client_header_buffer_size 32k; #上传文件大小限制
	large_client_header_buffers 4 64k; #设定请求缓冲
	client_max_body_size 8m; #设定请求缓冲
	sendfile on; #开启高效文件传输模式,对于普通应用设为on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。
	autoindex on; #开启目录列表访问,合适下载服务器,默认关闭。
	tcp_nopush on; #防止网络阻塞
	tcp_nodelay on; #防止网络阻塞
	keepalive_timeout 120; #长连接超时时间,单位是秒
	
	#FastCGI相关参数是为了改善网站的性能:减少资源占用,提高访问速度。
	fastcgi_connect_timeout 300;
	fastcgi_send_timeout 300;
	fastcgi_read_timeout 300;
	fastcgi_buffer_size 64k;
	fastcgi_buffers 4 64k;
	fastcgi_busy_buffers_size 128k;
	fastcgi_temp_file_write_size 128k;

    #gzip模块设置
	gzip on; #开启gzip压缩输出
	gzip_min_length 1k; #最小压缩文件大小
	gzip_buffers 4 16k; #压缩缓冲区
	gzip_http_version 1.0; #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
	gzip_comp_level 2; #压缩等级
	gzip_types text/plain application/x-javascript text/css application/xml; #压缩类型
	gzip_vary on; #增加响应头'Vary: Accept-Encoding'
	limit_zone crawler $binary_remote_addr 10m; #开启限制IP连接数的时候需要使用

②、server 块

  • 配置网络监听
  • 配置https服务
  • 基于名称的虚拟主机配置
  • 基于IP的虚拟主机配置

这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了节省互联网服务器硬件成本。

每个 http 块可以包括多个 server 块,而每个 server 块就相当于一个虚拟主机。而每个 server 块也分为全局 server 块,以及可以同时包含多个 locaton 块。

  • 全局 server 块:最常见的配置是本虚拟机主机的监听配置和本虚拟主机的名称或 IP 配置。
  • location 块:一个 server 块可以配置多个 location 块。
	#一个 Server 就是一个虚拟主机192.168.15.131
    server {
        listen       80; #配置监听端口
        server_name  localhost;  # 为虚拟机指定 IP 或者是域名

        charset utf-8; #配置字符集
        #access_log  logs/host.access.log  main; #配置本虚拟主机的访问日志
        location / {
        	 #用于指定访问根目录时,访问虚拟主机的web目录
        	 #root是配置服务器的默认网站根目录位置,默认为nginx安装主目录下的html目录
            root   html;
             #在不指定访问具体资源时,默认的展示资源的列表
            index  index.html index.htm;
        }

        error_page 404             /404.html; #配置404错误页面
   		 error_page 500 502 503 504 /50x.html; #配置50x错误页面
        location = /50x.html {
            root   html;
        }
    }
    #配置https服务,安全的网络传输协议,加密传输,端口443
server {
    listen       443 ssl;
    server_name  localhost;

    ssl_certificate      cert.pem;
    ssl_certificate_key  cert.key;

    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;

    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;

    location / {
        root html; #root是配置服务器的默认网站根目录位置,默认为nginx安装主目录下的html目录
		index index.html index.htm; #配置首页文件的名称
		
		proxy_pass http://127.0.0.1:88; #反向代理的地址
		proxy_redirect off; #是否开启重定向
		#后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header Host $host;
		#以下是一些反向代理的配置,可选。
		client_max_body_size 10m; #允许客户端请求的最大单文件字节数
		client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数,
		proxy_connect_timeout 90; #nginx跟后端服务器连接超时时间(代理连接超时)
		proxy_send_timeout 90; #后端服务器数据回传时间(代理发送超时)
		proxy_read_timeout 90; #连接成功后,后端服务器响应时间(代理接收超时)
		proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
		proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的设置
		proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2)
		proxy_temp_file_write_size 64k;  #设定缓存文件夹大小
    }

location 块的主要作用是基于 Nginx 服务器接收到的请求字符串(例如 server_name/uri-string),对虚拟主机名称(也可以是 IP 别名)之外的字符串(例如 前面的 /uri-string)进行匹配,对特定的请求进行处理。地址定向、数据缓存和应答控制等功能,还有许多第三方模块的配置也在这里进行。

以上就是关于Nginx配置文件的基本描述,当然光是听着理论是非常懵的,下面我们还是通过示例来加以理解,首先是反向代理。

五、Nginx实现反向代理

5.1 概念

(1)正向代理的概念
正向代理,简单的说就像是一个跳板,它隐藏了真实的请求客户端,服务端不知道真实的客户端是谁,客户端请求的服务都由代理服务器代替来请求。

简单的说,我是一个用户,我访问不了某网站,但是我能访问一个代理服务器,这个代理服务器呢,他能访问那个我不能访问的网站,于是我先连上代理服务器,告诉他我需要那个无法访问网站的内容,代理服务器去取回来,然后返回给我。
在这里插入图片描述

举个例子来说:国内的用户想要访问百度时,直接访问是会被阻挡的。所以这个时候把请求发送到另外一个代理服务器,再由代理服务器去访问这样就可以访问到 百度服务器上了,由其代为转发请求和接收响应内容。

当正向代理出现多个请求客户端时,是这样的:
在这里插入图片描述
简单来说,正向代理指的是一对一或者多对一,服务端不知道发送请求的客户端是哪些人。

(2)反向代理的概念
反向代理恰好跟正向代理相反。同时反向代理一般是负载均衡的一个原理。按照以上所述,正向代理是一对一或多对一,那么反向代理就是一对多(还可以多对多),如下图所示:
在这里插入图片描述

反向代理的客户端对代理是无感知的,因为客户端不需要任何配置就可以访问,我们只需要将请求发送到反向代理服务器,然后由反向代理服务器去选择目标服务器获取数据后返回给客户端,此时反向代理服务器和目标服务器对外来说就像是一个服务器,而暴露在外的就是代理服务器地址,从而隐藏了真实的服务器IP地址。

在这里插入图片描述
反向代理隐藏了真实的服务端,当我们请求http://www.baidu.com的时候,背后可能有成千上万台服务器为我们服务,但具体是哪一台服务器,我们根本不知道,当然也不需要知道,我们只需要知道反向代理服务器是谁就好了,而 http://www.baidu.com 就是这个反向代理服务器,反向代理服务器会帮我们把请求转发到真实的服务器那里去。

反向代理和正向代理的区别:根本的区别在于两者代理的对象不一样:正向代理代理的对象是客户端,反向代理代理的对象是服务端。

根据理解,给出一个草图:
在这里插入图片描述

5.2、Nginx配置反向代理案例(一)

(1)实现效果

  • 打开浏览器,在浏览器的地址栏中输入www.123.com,回车之后就会反问Linux系统中运行的Tomcat服务器的主页面。
    在这里插入图片描述
    在这里插入图片描述

(2)准备工作【安装启动tomcat】

准备工作:在Linux中安装Jdk、Nginx以及Tomcat,Tomcat使用端口号8080。

  • 下载Tomcat
    wget https://archive.apache.org/dist/tomcat/tomcat-7/v7.0.105/bin/apache-tomcat-7.0.105.tar.gz
  • 解压即安装tar -zxvf apache-tomcat-7.0.105.tar.gz
  • 移动到local目录下mv apache-tomcat-7.0.105 /usr/local/tomcat
  • 启动tomcat/usr/local/tomcat/bin/startup.sh
  • 如果需要关闭tomcat/usr/local/tomcat/bin/startup.sh
  • 关闭防火墙systemctl stop firewalld

(3)修改Windows中的hosts域名映射

打开 C:\Windows\System32\drivers\etc\,在该目录下有一个hosts文件,将该文件进行拷贝备份,避免修改后不知道怎么改回去,打开hosts文件,添加以下配置代码:

#虚拟机域名       映射的网址
192.168.15.131  www.123.com

(4)修改Nginx的配置文件并启动Nginx

  • 第一步:vi /usr/local/nginx/conf/nginx.conf
  • 第二步:
server {
        listen       80;
        server_name  192.168.15.131; # 配置这里为自己虚拟机的ip
        
        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            proxy_pass http:127.0.0.1:8080; # 这里配置的是
            root   html;
            index  index.html index.htm;
        }
}
  • 第三步:编辑完成之后保存退出,启动Nginx,/usr/local/nginx/sbin/nginx
    如果Nginx已经启动,那么就使用重新加载配置文件的命令。

  • 第四步:启动Nginx和Tomcat之后,在浏览器访问www.123.com即可出现Tomcat的界面
    在这里插入图片描述

  • 第五步:关闭Tomcat的命令 /usr/local/tomcat/bin/shutdown.sh

5.3、Nginx配置反向代理案例(二)

(1)实现效果

使用Nginx实现根据访问的路径不同,跳转到不同端口的服务中,例如:
在浏览器中输入【http://192.168.15.131/edu/a.html】时,会跳转到Tomcat为8080端口的服务中去,
在这里插入图片描述

在浏览器中输入【http://192.168.15.131/vod/a.html】时,会跳转到Tomcat为8081端口的服务中去,
在这里插入图片描述

在这里插入图片描述

【图来源于网络 https://caochenlei.blog.csdn.net/article/details/108300342】

(2)准备工作

需要安装两个Tomcat,同时修改其中的一个Tomcat的端口,关闭防火墙,启动tomcat。

  • 第一步:获取tomcat安装包
版本号可以自己设置
wget https://archive.apache.org/dist/tomcat/tomcat-7/v7.0.105/bin/apache-tomcat-7.0.105.tar.gz
  • 第二步:解压Tomcat
tar -zxvf apache-tomcat-7.0.105.tar.gz
mv apache-tomcat-7.0.105 /usr/local/tomcat8080

tar -zxvf apache-tomcat-7.0.105.tar.gz
mv apache-tomcat-7.0.105 /usr/local/tomcat8081
  • 第三步:删除tomcat8081中的配置文件
    rm -f /usr/local/tomcat8081/conf/server.xml
  • 第四步:复制以下内容,自己添加一个配置文件
    vim /usr/local/tomcat8081/conf/server.xml
    内容如下:【改动的地方就是端口】
<?xml version='1.0' encoding='utf-8'?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<!-- Note:  A "Server" is not itself a "Container", so you may not
     define subcomponents such as "Valves" at this level.
     Documentation at /docs/config/server.html
 -->
<Server port="8006" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <!-- Security listener. Documentation at /docs/config/listeners.html
  <Listener className="org.apache.catalina.security.SecurityListener" />
  -->
  <!--APR library loader. Documentation at /docs/apr.html -->
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
  <Listener className="org.apache.catalina.core.JasperListener" />
  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
  <!-- Global JNDI resources
       Documentation at /docs/jndi-resources-howto.html
  -->
  <GlobalNamingResources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>
  <!-- A "Service" is a collection of one or more "Connectors" that share
       a single "Container" Note:  A "Service" is not itself a "Container",
       so you may not define subcomponents such as "Valves" at this level.
       Documentation at /docs/config/service.html
   -->
  <Service name="Catalina">
    <!--The connectors can use a shared executor, you can define one or more named thread pools-->
    <!--
    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
        maxThreads="150" minSpareThreads="4"/>
    -->
    <!-- A "Connector" represents an endpoint by which requests are received
         and responses are returned. Documentation at :
         Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
         Java AJP  Connector: /docs/config/ajp.html
         APR (HTTP/AJP) Connector: /docs/apr.html
         Define a non-SSL HTTP/1.1 Connector on port 8080
    -->
    <Connector port="8081" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8444" />
    <!-- A "Connector" using the shared thread pool-->
    <!--
    <Connector executor="tomcatThreadPool"
               port="8081" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8444" />
    -->
    <!-- Define an SSL HTTP/1.1 Connector on port 8443
         This connector uses the BIO implementation that requires the JSSE
         style configuration. When using the APR/native implementation, the
         OpenSSL style configuration is required as described in the APR/native
         documentation -->
    <!--
    <Connector port="8444" protocol="org.apache.coyote.http11.Http11Protocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" />
    -->
    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <!--
    <Connector protocol="AJP/1.3"
               address="::1"
               port="8010"
               redirectPort="8444" />
    -->
    <!-- An Engine represents the entry point (within Catalina) that processes
         every request.  The Engine implementation for Tomcat stand alone
         analyzes the HTTP headers included with the request, and passes them
         on to the appropriate Host (virtual host).
         Documentation at /docs/config/engine.html -->
    <!-- You should set jvmRoute to support load-balancing via AJP ie :
    <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
    -->
    <Engine name="Catalina" defaultHost="localhost">
      <!--For clustering, please take a look at documentation at:
          /docs/cluster-howto.html  (simple how to)
          /docs/config/cluster.html (reference documentation) -->
      <!--
      <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
      -->
      <!-- Use the LockOutRealm to prevent attempts to guess user passwords
           via a brute-force attack -->
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- This Realm uses the UserDatabase configured in the global JNDI
             resources under the key "UserDatabase".  Any edits
             that are performed against this UserDatabase are immediately
             available for use by the Realm.  -->
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>
      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
        <!-- SingleSignOn valve, share authentication between web applications
             Documentation at: /docs/config/valve.html -->
        <!--
        <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
        -->
        <!-- Access log processes all example.
             Documentation at: /docs/config/valve.html
             Note: The pattern used is equivalent to using pattern="common" -->
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log." suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
    </Engine>
  </Service>
</Server>
  • 第五步:在每个tomcat的webapps目录下创建一个目录和一个html文件
# 在tomcat8080的webapps目录下创建文件夹
mkdir -p /usr/local/tomcat8080/webapps/edu
# 在tomcat8080的webapps/edu目录下创建html
echo "<h1>This is 8080 Port</h1>" > /usr/local/tomcat8080/webapps/edu/a.html


# 在tomcat8081的webapps目录下创建文件夹
mkdir -p /usr/local/tomcat8081/webapps/vod
# 在tomcat8080的webapps/vod目录下创建html
echo "<h1>This is 8081 Port</h1>" > /usr/local/tomcat8080/webapps/vod/a.html

  • 第六步:启动两个Tomcat
# 启动tomcat8080
/usr/local/tomcat8080/bin/startup.sh

# 启动tomcat8081
/usr/local/tomcat8081/bin/startup.sh

## 关闭命令
/usr/local/tomcat8080/bin/shutdown.sh
/usr/local/tomcat8081/bin/shutdown.sh

(3)修改Nginx配置文件

  • 修改配置文件:vim /usr/local/nginx/conf/nginx.conf
  • 添加以下内容:
server { 
       listen       80;  ## 监听80端口
       server_name  192.168.15.131; ##虚拟机的ip地址
       #charset koi8-r;
       #access_log  logs/host.access.log  main;

       location ~ /edu/ { ## 只要访问路径中包含edu就会进入到里面
           proxy_pass http://127.0.0.1:8080; ## 代理到8080端口,就会访问
       }

       location ~ /vod/ { ## 只要访问路径中包含vod就会进入到这里面
           proxy_pass http://127.0.0.1:8081; ## 代理到8081端口
       }
  • 重启Nginx
# 关闭Nginx
/usr/local/nginx/sbin/nginx -s stop

# 启动Nginx
/usr/local/nginx/sbin/nginx

(4)测试

在浏览器输入 http://192.168.15.131/edu/a.html
在这里插入图片描述

在浏览器输入 http://192.168.15.131/vod/a.html
在这里插入图片描述

5.4、反向代理的其他案例

假如我们自己做了一个项目,想让这个项目被其他人访问到,我们就需要去买一台云服务器,这里我是买了一台阿里云服务器,将我的博客项目打包部署到了云服务器上,同时我还去阿里云购买了一个域名,域名为【www.xxx.com】,并且进行了备案,在阿里云上将我的云服务器的外网IP地址【8.144.XXX.XXX】进行了如上案例一中修改hosts那样的域名配置,当访问【www.xxx.com】时就相当于访问【8.144.XXX.XXX】这个地址,然后在云服务器上安装了Nginx,同时在Nginx中添加了以下配置:

加入这个配置之后,那么当我们访问【www.xxx.com】的时候,就会访问到我们的项目中了。当我们输入【www.xxx.com】时,就相当于输入了【http://8.144.XXX.XXX/】,这样的访问最后是包含了 / ,而包含了/的请求在Nginx中默认代理到了8080端口,于是就直接访问到了我们的项目【http://8.144.XXX.XXX/8080】。

5.5、location指令说明

location ~ /admin {
           proxy_pass http://127.0.0.1:8080/admin;
        }

描述:该指令用于匹配URL
通配符:

  • =:用于不含正则表达式的 uri 前,要求请求字符串与 uri 严格匹配,如果匹配成功,就停止继续向下搜索并立即处理该请求。
  • ~:用于表示 uri 包含正则表达式,并且区分大小写。
  • ~*:用于表示 uri 包含正则表达式,并且不区分大小写。
  • ^~:用于不含正则表达式的 uri 前,要求 Nginx 服务器找到标识 uri 和请求字符串匹配度最高的 location 后,立即使用此 location 处理请求,而不再使用 location 块中的正则 uri 和请求字符串做匹配。

注意 如果 uri 包含正则表达式,则必须要有 ~ 或者 ~* 标识。

六、Nginx实现负载均衡

6.1 概念

客户端发送多个请求到服务器,服务器处理请求,有一些可能要与数据库进行交互,服务器处理完毕后,再将结果返回给客户端。

这种架构模式对于早期的系统相对单一,并发请求相对较少的情况下是比较适合的,成本也低。但是随着信息数量的不断增长,访问量和数据量的飞速增长,以及系统业务的复杂度增加,这种架构会造成服务器相应客户端的请求日益缓慢,并发量特别大的时候,还容易造成服务器直接崩溃。很明显这是由于服务器性能的瓶颈造成的问题,那么如何解决这种情况呢?

我们首先想到的可能是升级服务器的配置,比如提高 CPU 执行频率,加大内存等提高机器的物理性能来解决此问题,但是我们知道摩尔定律的日益失效,硬件的性能提升已经不能满足日益提升的需求了。最明显的一个例子,天猫双十一当天,某个热销商品的瞬时访问量是极其庞大的,那么类似上面的系统架构,将机器都增加到现有的顶级物理配置,都是不能够满足需求的。那么怎么办呢?

上面的分析我们去掉了增加服务器物理配置来解决问题的办法,也就是说纵向解决问题的办法行不通了,那么横向增加服务器的数量呢?这时候集群的概念产生了,单个服务器解决不了,我们增加服务器的数量,然后将请求分发到各个服务器上,将原先请求集中到单个服务器上的情况改为将请求分发到多个服务器上,将负载分发到不同的服务器,也就是我们所说的负载均衡
在这里插入图片描述

6.2、实现效果

在浏览器输入地址:http://192.168.15.131/edu/a.html时,配置的负载均衡效果会将请求平均分配到8080和8081端口中。
输入:http://192.168.15.131/edu/a.html进行访问时会出现以下不同界面。
在这里插入图片描述

在这里插入图片描述
实现原理:
在这里插入图片描述

6.3、准备工作

(1)准备两台tomcat服务器【可以的话准备三四台也没问题】,一台服务器的端口为8080,另一台服务器的端口为8081;
(2)在两台tomcat服务器的webapps目录中,创建一个名称为edu的文件夹,在edu文件夹中创建一个a.html文件,用于测试。

6.4、在Nginx的配置文件中配置负载均衡

  • 第一步:修改Nginx的配置文件:vim /usr/local/nginx/conf/nginx.conf
  # 在http内添加以下代码
   upstream myserver {
       server 192.168.15.131:8080; # 这里添加负载均衡的服务器地址以及端口
       server 192.168.15.131:8081; # tomcat8081服务
   }

   server {
       listen       80;
       server_name  192.168.15.131;  # 这里要改成自己服务器的ip地址

       #charset koi8-r;

       #access_log  logs/host.access.log  main;

       location / {
           root   html;
            proxy_pass http://myserver; # 这里添加一个代理,指定我们配置负载均衡的服务名myserver
           index  index.html index.htm; 
       }
  • 第二步:修改nginx完毕之后,保存退出,重启Nginx。/usr/local/nginx/sbin/nginx
  • 第三步:在Tomcat8081的webapps文件夹中,创建一个edu文件夹,在里边创建a.html
# 创建文件夹
mkdir -p /usr/local/tomcat2/webapps/edu
# 添加html文件并加入内容
echo "<h1>This is 8081 Port</h1>" > /usr/local/tomcat8081/webapps/edu/a.html
  • 第四步:启动两个tomcat
#启动tomcat8080
/usr/local/tomcat8080/bin/startup.sh
#启动tomcat8081
/usr/local/tomcat8081/bin/startup.sh

6.5、测试

在浏览器的地址栏中输入:http://192.168.15.131/edu/a.html
在这里插入图片描述

然后刷新地址栏:
在这里插入图片描述

我们可以发现,每次刷新都会依次访问tomcat8080和tomcat8081服务,从而显示不同的页面。

  • 关闭服务的命令
#关闭Nginx
/usr/local/nginx/sbin/nginx -s quit
#关闭tomcat
/usr/local/tomcat8080/bin/shutdown.sh
/usr/local/tomcat8081/bin/shutdown.sh

6.6、Nginx负载均衡分配策略介绍

6.6.1、轮询【默认】

该策略会使得每个请求按时间顺序逐一分配到不同的后端服务器,如果其中某个后端服务器 down 掉,该策略能自动从轮询列表中剔除该服务。

将请求按顺序轮流地分配到后端服务器上,它均衡地对待后端的每一台服务器,而不关心服务器实际的连接数和当前的系统负载。

目的:为了加快网站的解析速度,可以把动态页面和静态页面由不同的服务器来进行解析,以此加快解析速度,降低原来单个服务器的压力。在Nginx中,没有配置其他策略时,默认是轮询策略。
在这里插入图片描述

6.6.2、权重(weight)

weight 代表权重,默认为1,权重越高被分配的客户端(请求)也就越多,weight 和访问比率成正比,用于后端服务器性能不均的情况

不同的后端服务器可能机器的配置和当前系统的负载并不相同,因此它们的抗压能力也不相同。给配置高、负载低的机器配置更高的权重,让其处理更多的请;而配置低、负载高的机器,给其分配较低的权重,降低其系统负载,加权轮询能很好地处理这一问题,并将请求顺序且按照权重分配到后端。

例如:

    upstream myserver {
        server 192.168.15.131:8080 weight=5; # 权重设置为5
        server 192.168.15.131:8081 weight=10; # 权重设置为10,10>5,所以请求时多会跳转到这个服务
    }

6.6.3、ip_hash(哈希)

每个请求按访问 ip 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决 session 的问题

源地址哈希法:根据获取客户端的IP地址,通过哈希函数计算得到一个数值,用该数值对服务器列表的大小进行取模运算,得到的结果便是客服端要访问服务器的序号。采用源地址哈希法进行负载均衡,同一IP地址的客户端,当后端服务器列表不变时,它每次都会映射到同一台后端服务器进行访问。

例如:

    upstream myserver {
        ip_hash;  # 直接在这里添加就可以了
        server 192.168.15.131:8080; 
        server 192.168.15.131:8081; 
    }

配置这个的意思为:假设我输入地址:http://192.168.15.131/edu/a.html 访问得到的是8080的tomcat,那么不管后面我再怎么刷新,我后面访问到的服务永远都是8080的tomcat,不会访问到8081。反之,假如我输入这个地址第一次访问到的是8081,那么后面访问到的一直都是8081。

6.6.4、fair(第三方)

按照后端服务器的响应时间来进行分配,相应时间短的优先分配

    upstream myserver {
        server 192.168.15.131:8080; 
        server 192.168.15.131:8081; 
        fair;  # 直接在这里添加就可以了
    }

例如我现在有tomcat8080、tomcat8081、tomcat8082,响应时间分别是3s、9s、1s,那么配置了这种第三方策略会优先分配响应时间短的服务,也就是8082的服务。

七、Nginx实现动静分离

7.1 概念

Nginx 动静分离简单来说就是把动态跟静态请求分开,不能理解成只是单纯的把动态页面和静态页面物理分离。严格意义上说应该是动态请求跟静态请求分开,可以理解成使用 Nginx 处理静态页面,Tomcat 处理动态页面。动静分离从目前实现角度来讲大致分为两种,一种是纯粹把静态文件独立成单独的域名,放在独立的服务器上,也是目前主流推崇的方案;另外一种方法就是动态跟静态文件混合在一起发布,通过 Nginx 来分开。
在这里插入图片描述

通过 location指定不同的后缀名实现不同的请求转发。通过expires参数设置,可以使浏览器缓存过期时间,减少与服务器之前的请求和流量。具体 Expires定义:是给一个资源设定一个过期时间,也就是说无需去服务端验证,直接通过浏览器自身确认是否过期即可,所以不会产生额外的流量。此种方法非常适合不经常变动的资源。(如果经常更新的文件,不建议使用 Expires来缓存),我这里设置3d,表示在这3天之内访问这个URL,发送一个请求,比对服务器该文件最后更新时间没有变化,则不会从服务器抓取,返回状态码304,如果有修改,则直接从服务器重新下载,返回状态码200。

7.2、准备工作

我们在根目录下创建一个data目录,在data目录下创建www目录和image目录,www目录用于存放静态html文件,image目录用于存放图片。

# 到根目录下
cd /
# 创建目录
mkdir data
cd data
mkdir www
mkdir image
# 在www下添加一个html文件
echo "<h1>This is test Nginx html</h1>" > /data/www/t1.html
# 还需要在image目录下上传一张图片
cd /data/image
yum install -y lrzsz    # 安装上传文件的插件
rz   #安装成功之后使用rz命令上传图片

7.3、实现效果

  • 当我们输入网址:http://192.168.15.131/www/t1.html 时能够访问到/data/www/目录下的html
    文件:
    在这里插入图片描述
  • 当我们输入:http://192.168.15.131/image/1.png 时能够访问到/data/image/目录下的图片。
    在这里插入图片描述
  • 原理:
    在这里插入图片描述

7.4、更改Nginx配置文件

  • 配置文件:`vim /usr/local/nginx/conf/nginx.conf
    server {
        listen       80;
        server_name  192.168.15.131; #这里设置成自己的ip

        location /www/ {   # 配置当请求中包含 /www/ 就会去 /data/ 目录下查找
            root   /data/;  
            index  index.html index.htm;
        }

        location /image/{
            root /data/;
            autoindex on;  # 这个的作用为展示目录,后面介绍
        }
  • 保存退出,重启Nginx
/usr/local/nginx/sbin/nginx -s stop
/usr/local/nginx/sbin/nginx 

7.5、测试效果

  • 当访问:http://192.168.15.131/www/t1.html 时,会访问到 /data/www/t1.html
    在这里插入图片描述
  • 当输入:http://192.168.15.131/image/ 时,会展示该目录列表
    在这里插入图片描述
    原因是因为我们在Nginx的配置文件中,关于图片这块设置了 autoindex on;
  • 当输入:http://192.168.15.131/image/1.png 时,会展示:
    在这里插入图片描述

八、Nginx配置实现集群高可用

8.1、概念

前边我们学习了反向代理、负载均衡、动静分离,但试想一下,如果Nginx挂掉了,那么服务肯定就没有了,有没有一种解决方案,可以保证Nginx挂掉了,服务也可以照常使用,答案肯定是有的,这就是我们接下来要学习的高可用集群,采用的是一主一备的模式,当主节点Nginx挂掉,备份服务器Nginx立刻跟上,这样就保证了服务的高可用性。

8.2、实现效果

配置了Nginx的集群,当主nginx服务器挂掉以后,服务依然能够正常使用。
在这里插入图片描述

8.3、准备工作

准备工作:
(1)需要准备两台服务器,这里我使用的是:192.168.15.131和132,两台服务器,
(2)需要在两台服务器上安装好Nginx,
(3)在两台服务器上运行以下命令分别安装 keepalived。

  • 第一步:运行yum install -y keepalived 对 keepalived 进行安装;
  • 第二步:查看keepalived的版本 rpm -q -a keepalived
  • 第三步:keepalived安装之后,它的配置文件在 etc/keepalived/keepalived.conf
  • 第四步:删除这个配置文件 rm -f /etc/keepalived/keepalived.conf
  • 第五步:新建配置文件,并将内容替换成我们自己的 vi /etc/keepalived/keepalived.conf
# 主机的配置
global_defs {
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   #邮件服务器通知地址(暂不配置,默认即可)
   smtp_server 192.168.200.1
   
   #邮件服务器超时时间(暂不配置,默认即可)
   smtp_connect_timeout 30
   
   #当前虚拟机的IP地址
   router_id 192.168.15.131
}

vrrp_script Monitor_Nginx {    # 配置检测,定时去检测以下Nginx是否活着
 #检测脚本执行的路径
 script "/etc/keepalived/nginx_check.sh"   

 #检测脚本执行的间隔
 interval 2      

#检测脚本执行的权重                           
 weight 2                                   
}

vrrp_instance VI_1 {  # 虚拟IP的一些配置
    state MASTER          # 配置这个机器是主机(MASTER)还是从机(BACKUP)
    interface eth0       #当前机器的网卡名称  可用ifconfig查看
    virtual_router_id 51  #虚拟路由的编号,主备必须一致
    priority 100          #主、备机取不同的优先级,主机值较大,备份机值较小
    advert_int 1          #(VRRP Multicast广播周期秒数)
    authentication {
        auth_type PASS   #(VRRP认证方式)
        auth_pass 1111   #(密码)
    }
    track_script {
		Monitor_Nginx   #(调用nginx进程检测脚本)
	}
    virtual_ipaddress {
        192.168.15.50    #虚拟IP地址
    }
}
# 从机的配置
global_defs {
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   #邮件服务器通知地址(暂不配置,默认即可)
   smtp_server 192.168.200.1
   
   #邮件服务器超时时间(暂不配置,默认即可)
   smtp_connect_timeout 30
   
   #当前虚拟机的IP地址
   router_id 192.168.15.132
}

vrrp_script Monitor_Nginx {    # 配置检测,定时去检测以下Nginx是否活着
 #检测脚本执行的路径
 script "/etc/keepalived/nginx_check.sh"   

 #检测脚本执行的间隔
 interval 2      

#检测脚本执行的权重                           
 weight 2                                   
}

vrrp_instance VI_1 {  # 虚拟IP的一些配置
    state BACKUP  # 配置这个机器是主机(MASTER)还是从机(BACKUP)
    interface ens32       #当前机器的网卡名称  可用ifconfig查看
    virtual_router_id 51  #虚拟路由的编号,主备必须一致
    priority 90          #主、备机取不同的优先级,主机值较大,备份机值较小
    advert_int 1          #(VRRP Multicast广播周期秒数)
    authentication {
        auth_type PASS   #(VRRP认证方式)
        auth_pass 1111   #(密码)
    }
    track_script {
		Monitor_Nginx   #(调用nginx进程检测脚本)
	}
    virtual_ipaddress {
        192.168.15.50    #虚拟IP地址
    }
}
  • 第六步:新增keepalived的检测脚本 vim /etc/keepalived/nginx_check.sh
#!/bin/bash
A=·`ps -C nginx -no-header |wc -1`
if [ $A -eq 0 ];then
 	/usr/local/nginx/sbin/nginx
 	sleep 2
 	if [`ps -C nginx --no-header |wc -1` -eq 0];then
 		killall keepalived
 	fi
fi
  • 第七步:启动keepalived服务 service keepalived start
  • 第八步:查看keepalived是否启动 ps -aux|grep keepalived
    在这里插入图片描述

注意

  • 以上需要准备两台虚拟机,同时都要装上nginx和keepalived,同时keepalived的脚本文件以及配置文件都要进行修改。
  • 一定要注意keepalived.conf中的修改:router_id、state、interface的值是需要修改的。

8.4、测试

  • 分别启动两台服务器的nginx以及keepalived【前面已经启动了keepalived】
# 在192.168.15.131和132服务器中分别输入命令
service keepalived start
/usr/local/nginx/sbin/nginx 
  • 记得关闭防火墙:systemctl stop firewalld
  • 在浏览器输入虚拟ip地址: http://192.168.15.50
    在这里插入图片描述
  • 在设置成主机的服务器中输入 ip -a可查看绑定信息
    在这里插入图片描述
  • 我们将131服务器的nginx和keepalived停掉,然后再访问:http://192.168.15.50
 /usr/local/nginx/sbin/nginx -s stop
systemctl stop keepalived

在这里插入图片描述
我们发现,虚拟IP还是能够访问到Nginx的页面,同时我们在131的服务器中再去看以下ip信息
输入:ip a
在这里插入图片描述
我们发现,在131关闭nginx以及keepalived之后,就没有绑定信息了,我们再去查看132的服务器
在这里插入图片描述
测试完毕,当主机131挂掉之后,集群会将备用机132设置为主机,让服务能够正常运行。
那么,我们如果再将131中的服务启动会怎么样呢?

service keepalived start
/usr/local/nginx/sbin/nginx 

在这里插入图片描述
结果证明,当挂掉的主机再次复活之后,会被继续当做主机。

8.5、总结

在这里插入图片描述
我们设置了两台服务器131和132,服务器上都安装了Nginx和keepalived,我们将131的nginx设置成了主机,132的nginx设置成了从机,主服务器是我们真正访问的,主服务器要对外绑定一个虚拟IP【50】,当我们访问虚拟IP的时候,肯定访问到主服务器,当主机挂掉以后,keepalived会通过脚本校测到主机挂掉了,然后自动切换到从机,把虚拟IP绑定到了从机的服务器中,所以当主机挂掉以后,从机可以充当主机进行使用继续进行访问。这里面的重点就是keepalived以及脚本。

8.6、高可用配置文件详解

  • keepalived.conf文件中的配置介绍
# 第一部分:全局配置
global_defs {  
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   #邮件服务器通知地址(暂不配置,默认即可)
   smtp_server 192.168.200.1
   
   #邮件服务器超时时间(暂不配置,默认即可)
   smtp_connect_timeout 30
   
   #当前虚拟机的名称,配置可访问到主机,主机名可在/etc/hosts中查看   【重要】 
   router_id 192.168.15.131  
}


# 第二部分:脚本的配置
vrrp_script Monitor_Nginx {    # 配置检测,定时去检测以下Nginx是否活着
 #检测脚本执行的路径,脚本中的条件成立会做一些操作
 script "/etc/keepalived/nginx_check.sh"   

 #检测脚本执行的间隔
 interval 2      

#设置当前服务器执行的权重                           
 weight 2                                   
}

# 第三部分:虚拟IP的配置
vrrp_instance VI_1 {  # 虚拟IP的一些配置
    state MASTER   # 配置这个机器是主机(MASTER)还是从机(BACKUP)【重要】
    interface eth0       #绑定的网卡名称  可用ifconfig查看【重要】
    virtual_router_id 51  # 虚拟路由的编号,主备必须一致【重要】
    priority 100          #主、备机取不同的优先级,主机值较大,备份机值较小【重要】
    advert_int 1          #(VRRP Multicast广播周期秒数) 每隔多长时间检测一次心跳,单位:秒
    authentication {   # 权限校验的方式
        auth_type PASS   #(VRRP认证方式)
        auth_pass 1111   #(密码)
    }
    track_script {
		Monitor_Nginx   #(调用nginx进程检测脚本)
	}
    virtual_ipaddress {
        192.168.15.50    #虚拟IP地址 【重要】
    }
}
  • 脚本文件nginx_check.sh介绍
#!/bin/bash
A=·`ps -C nginx -no-header |wc -1`
if [ $A -eq 0 ];then
	/usr/local/nginx/sbin/nginx        #Nginx启动脚本的位置
	sleep 2
	if [`ps -C nginx --no-header |wc -1` -eq 0];then
		killall keepalived
	fi
fi

主服务器挂掉了,杀掉主机中的keepalived,然后让从服务器就替换主服务器成为主机。

九、Nginx的执行原理

9.1、Nginx的线程模型

  • Nginx默认采用多进程工作方式,Nginx启动后,会运行一个master进程和多个worker进程
    我们启动Nginx时,使用 【ps -ef | grep nginx】可以看到下图所示:
    在这里插入图片描述
  • master充当整个进程组与用户的交互接口,同时对进程进行监护,管理worker进程来实现重启服务、平滑升级、更换日志文件、配置文件实时生效等功能。
  • worker用来处理基本的网络事件,worker之间是平等的,他们共同竞争来处理来自客户端的请求。

在这里插入图片描述

9.2、Nginx是如何工作的?

在这里插入图片描述
如上图所示,当客户端来了一个请求,请求就会到Master手上,而Master就相当于一个管理员,它会把有请求过来的消息分发给Worker,而worker是可能有多个的,多个worker之间通过争抢的机制来获取请求任务,当其中一个worker得到任务之后,就会使用tomcat来完成对应的操作。

worker对于连接是采用争抢的模式,谁先抢到就先交给谁处理,如果想要重新更新配置,由于已经抢到任务的worker不会参与争抢,那些空闲的worker就会去争抢连接,拿到连接后会自动更新配置信息,当那些有任务的worker完成任务后,会自动更新配置,这样就实现了无缝热部署。由于每个worker是独立的进程,如果有其中的一个worker出现问题,并不会影响其它worker继续进行争抢,在实现请求的过程,不会造成服务中断,建议worker数和服务器的cpu数相等是最为适宜的。

9.3、Master-Worker模式的好处

  • 首先,对于每个worker进程来说,独立的进程不需要加锁,所以省掉了加锁带来的开销,同事在编程以及问题排查的时候也会方便很多。
  • 其次,采用独立的进程,相互之间不会影响,一个进程退出后其他的进程还在工作,服务不会中断,Master进程会很快的启动新的worker进程。
  • 假设worker进程异常退出了,肯定是程序出现BUG了,异常退出会导致当前worker上的所有请求都失败,不过不会影响其他的请求,从而降低了风险。
  • 此模式还支持热部署,当我们在启动Nginx的情况下修改了Nginx的配置文件,我们可以使用/nginx -s reload的方式重新加载配置文件,而不是停掉Nginx服务重新启动。

9.4、设置多少个worker才合适呢?

  • Nginx和Redis类似,都采用了IO多路复用机制【Windows下安装Nginx无此功能】,每个worker都是一个独立的进程,但每个进程里面只有一个主进程,通过 异步阻塞 的方式来处理请求,因此即使是成千上万个请求也不在话下。
  • 每个Worker线程可以把一个cpu的性能发挥到极致。因此worker的数目和服务器的cpu数相等最为适宜。因为设置少了会浪费cpu,设置多了会造成cpu频繁切换上下文带来损耗。

9.5、如何设置Nginx的worker数量

worker  processes 4  #  work 绑定cpu(4 work绑定4cpu)。
worker  cpu  affinity  0001 0010 0100 1000

# work绑定cpu (4 work绑定 8cpu中的4个)。
worker..cpu affinity 0000001 00000010 00000100 00001000


连接数 worker_connectione

  • 这个值是表示每个worker进程所能建立连接的最大值,所以,一个nginx能建立的最大连接数,应该是【worker_connections * worker_processes】。
  • 当然,这里说的是最大连接数,对于HTTP请求本地资源来说,能够支持的最大并发数量是【worker_connections * worker_processes】,如果是支持http1.1的浏览器每次访问要占两个连接,所以普通的静态访问最大并发数是:【worker_connections * worker_processes / 2】,而如果是HTTP作为反向代理来说,最大并发数量应该是【worker_connections * worker_processes / 4】。因为作为反向代理服务器,每个并发会建立与客户端的链接和后端服务器的链接会占用两个连接。

9.6、 当客户端发送一个请求,会占用worker的几个连接数?

答案:2个或者4个。当访问静态资源时,就是占用两个连接数,当要使用tomcat访问数据库时就是4个连接数。

  • 如果只访问nginx的静态资源,一个发送请求会占用了 woker 的 2 个连接数
  • 而如果是作为反向代理服务器,一个发送请求会占用了 woker 的 4 个连接数

9.7、Nginx有一个Master,四个Worker,每个Worker支持最大的连接数是1024,那么worker支持的最大并发数是多少?

答案:首先得知道 worker支持的最大连接数【worker_connections】= 4 *1024 ,然后我们上面一个问题可以知道,一个请求可能会占用worker两个请求或者四个请求,那么就使用worker_connections/2或者是worker_connections/4,答案就是-----1024或者2048。

普通的静态访问最大并发数是:【worker_connections * worker_processes / 2】,
如果是HTTP作为反向代理来说,最大并发数量应该是【worker_connections * worker_processes / 4】。

  • worker_connections:每个worker支持的最大连接数
  • worker_processes :有多少个worker
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐