【网络架构】Nginx

目录

一、I/O模型

1.1 Linux 的 I/O

 1.2 零拷贝技术

1.3 网络IO模型 

1.3.1 阻塞型 I/O 模型(blocking IO)​编辑

1.3.2非阻塞型 I/O 模型 (nonblocking IO)​编辑

1.3.3 多路复用 I/O 型 ( I/O multiplexing )​编辑

1.3.4 信号驱动式 I/O 模型 (signal-driven IO)​编辑

1.3.5异步 I/O 模型 (asynchronous IO)​编辑

 二、Nginx概述

2.1 Nginx架构

2.2 Nginx进程架构

2.3 Nginx模块

三、编译安装Nginx

3.1 编译安装Nginx 

3.2  创建Service文件

3.3 yum安装

3.4 平滑升级及命令、信号使用

3.4.1 详细显示编译情况信息

3.4.2 发送信号

3.4.3 飞行升级

四、配置Nginx

4.1 全局配置

4.1.1 关闭版本或修改版本

4.1.2 修改启动的进程数

4.1.3 cpu与work 进程绑定

4.1.4 PID 路径

4.1.5 nginx进程的优先级(work进程的优先级)

4.1.6 调试work进程打开的文件的个数

4.1.7 服务是否已后台方式运行

4.1.8 只有 master进程没有 work进程

4.2 event事件

4.3 http模块

4.3.1 mime

4.3.2 server下的root

 4.3.3 server块构建虚拟主机

4.3.4 alias别名

4.3.5 location匹配

4.3.6 access模块(四层控制)

 4.3.7 验证模块

4.3.8 自定义错误页面

4.3.9 日志位置存放

4.3.10 检测文件是否存在

4.3.11 长连接

4.3.12 作为下载服务器配置

4.3.13 用户上传资料

4.3.14 其他设置

 五、高级配置

5.1 状态页

5.2 Nginx第三方模块echo

 5.3 变量

5.3.1 内置

5.3.2 自定义变量

5.4 自定义访问日志

5.4.1 日志的格式(可自由指定)

5.4.2 自定义json格式日志

5.5 Nginx压缩功能

5.6 https功能(签名证书)

5.7 升级openssl

5.8 自定义图标

 六、重写功能rewrite

6.1 rewrite与location的区别

6.2 四个模块指令

6.2.1 if指令

6.2.2 return

6.2.3 set指令

6.2.4 break指令

6.3 rewrite指令

 6.4 防盗链

七、反向代理

7.1 实现 http 反向代理

7.1.1 http 协议反向代理

7.1.1.1 反向代理配置参数

7.1.1.2 实战案例: 反向代理单台web服务器

7.1.1.3 实战案例:动静分离

7.1.1.4反向代理示例:缓存功能

7.1.1.5 实现反向代理客户端 IP 透传

7.1.1.6 http反向代理负载均衡

7.1.1.7 Nginx tcp负载均衡四层


一、I/O模型

1.1 Linux 的 I/O

  • 磁盘I/O 磁盘I/O是进程向内核发起系统调用,请求磁盘上的某个资源比如是html 文件或者图片,然后内核通过相应的驱动程序将目标文件加载到内核的内存空间,加载完成之后把数据从内核内存再复制给进程内存,如果是比较大的数据也需要等待时间

  • 网络I/O : 一切皆文件,本质为对socket文件的读写,在/proc/PID/fd下形成临时文件来存储这次访问的基本信息 网络通信就是网络协议栈到用户空间进程的IO就是网络IO

过程:

1.客户端发起请求 先发送到网卡   
2.网卡收到的报文复制到内核空间
3.内核空间再复制到用户空间的应用程序空间
4.nginx 分析得到一个磁盘页面文件
5.再将需求反馈给内核空间,应为应用程序没有权限从磁盘上直接读取文件,需要依靠内核
6.内核去磁盘上找到所需要的文件,加载到内核空间
7.加载后再复制到用户空间
8.用户空间构建响应报文,交给内核空间,内核空间再复制给网卡,返回给用户
整个过程会来回切换用户空间,内核空间那么我们可以再次基础上做优化处理

 1.2 零拷贝技术

传统IO接口模型图

零拷贝就是上述问题的一个解决方案,通过尽量避免拷贝操作来缓解 CPU 的压力。零拷贝并没有真正做到“0”拷贝,它更多是一种思想,很多的零拷贝技术都是基于这个思想去做的优化。

MMAP ( Memory Mapping )

mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问。

mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。

实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必再调用read,write等系统调用函数。相反,内核空间对这段区域的修改也直接反映用户空间,从而可以实现不同进程间的文件共享。内存映射减少数据在用户空间和内核空间之间的拷贝操作,适合大量数据传输

 

send file

类似一个 软连接的技术

1.3 网络IO模型 

阻塞型、非阻塞型、复用型、信号驱动型、异步

1.3.1 阻塞型 I/O 模型(blocking IO)

阻塞IO模型是最简单的I/O模型,用户线程在内核进行IO操作时被阻塞用户线程通过系统调用read发起I/O读操作,由用户空间转到内核空间。内核等到数据包到达后,然后将接收的数据拷贝到用户空间,完成read操作用户需要等待read将数据读取到buffer后,才继续处理接收的数据。整个I/O请求的过程中,用户线程是被阻塞的,这导致用户在发起IO请求时,不能做任何事情,对CPU的资源利用率不够

  • 优点:程序简单,在阻塞等待数据期间进程/线程挂起,基本不会占用 CPU 资源

  • 缺点:每个连接需要独立的进程/线程单独处理,当并发请求量大时为了维护程序,内存、线程切换开销较大,apache 的preforck使用的是这种模式。

同步阻塞:程序向内核发送I/O请求后一直等待内核响应,如果内核处理请求的IO操作不能立即返回,则进程将一直等待并不再接受新的请求,并由进程轮训查看I/O是否完成,完成后进程将I/O结果返回给Client,在IO没有返回期间进程不能接受其他客户的请求,而且是有进程自己去查看I/O是否完成,这种方式简单,但是比较慢,用的比较少。

1.3.2非阻塞型 I/O 模型 (nonblocking IO)

用户线程发起IO请求时立即返回。但并未读取到任何数据,用户线程需要不断地发起IO请求,直到数据到达后,才真正读取到数据,继续执行。即 “轮询”机制存在两个问题:如果有大量文件描述符都要等,那么就得一个一个的read。这会带来大量的Context Switch(read是系统调用,每调用一次就得在用户态和核心态切换一次)。轮询的时间不好把握。这里是要猜多久之后数据才能到。等待时间设的太长,程序响应延迟就过大;设的太短,就会造成过于频繁的重试,干耗CPU而已,是比较浪费CPU的方式,一般很少直接使用这种模型,而是在其他IO模型中使用非阻塞IO这一特性。

非阻塞:程序向内核发送请I/O求后一直等待内核响应,如果内核处理请求的IO操作不能立即返回IO结果,进程将不再等待,而且继续处理其他请求,但是仍然需要进程隔一段时间就要查看内核I/O是否完成。

查看上图可知,在设置连接为非阻塞时,当应用进程系统调用 recvfrom 没有数据返回时,内核会立即返回一个 EWOULDBLOCK 错误,而不会一直阻塞到数据准备好。如上图在第四次调用时有一个数据报准备好了,所以这时数据会被复制到 应用进程缓冲区 ,于是 recvfrom 成功返回数据当一个应用进程这样循环调用 recvfrom 时,称之为轮询 polling 。这么做往往会耗费大量CPU时间,实际使用很少

1.3.3 多路复用 I/O 型 ( I/O multiplexing )

I/O multiplexing 主要包括:select,poll,epoll三种系统调用,select/poll/epoll的好处就在于单个process就可以同时处理多个网络连接的IO。它的基本原理就是select/poll/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。当用户进程调用了select,那么整个进程会被block,而同时,kernel会“监视”所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。Apache prefork是此模式的select,work是poll模式。

1.3.4 信号驱动式 I/O 模型 (signal-driven IO)

信号驱动I/O的意思就是我们现在不用傻等着了,也不用去轮询。而是让内核在数据就绪时,发送信号通知我们。

调用的步骤是,通过系统调用 sigaction ,并注册一个信号处理的回调函数,该调用会立即返回,然后主程序可以继续向下执行,当有I/O操作准备就绪,即内核数据就绪时,内核会为该进程产生一个SIGIO 信号,并回调注册的信号回调函数,这样就可以在信号回调函数中系统调用 recvfrom 获取数据,将用户进程所需要的数据从内核空间拷贝到用户空间

此模型的优势在于等待数据报到达期间进程不被阻塞。用户主程序可以继续执行,只要等待来自信号处理函数的通知。

在信号驱动式 I/O 模型中,应用程序使用套接口进行信号驱动 I/O,并安装一个信号处理函数,进程继续运行并不阻塞

当数据准备好时,进程会收到一个 SIGIO 信号,可以在信号处理函数中调用 I/O 操作函数处理数据。

  • 优点:线程并没有在等待数据时被阻塞,内核直接返回调用接收信号,不影响进程继续处理其他请求因此可以提高资源的利用率

  • 缺点:信号 I/O 在大量 IO 操作时可能会因为信号队列溢出导致没法通知

1.3.5异步 I/O 模型 (asynchronous IO)

异步I/O 与 信号驱动I/O最大区别在于,信号驱动是内核通知我们何时开始一个I/O操作,而异步I/O是由内核通知我们I/O操作何时完成,两者有本质区别,相当于不用去饭店场吃饭,直接点个外卖,把等待上菜的时间也给省了。所有事情都交给内核处理。

这五种 I/O 模型中,越往后,阻塞越少,理论上效率也是最优前四种属于同步 I/O,因为其中真正的I/O 操作(recvfrom)将阻塞进程/线程,只有异步 I/O 模型才与 POSIX 定义的异步 I/O 相匹配

Nginx支持在多种不同的操作系统实现不同的事件驱动模型,但是其在不同的操作系统甚至是不同的系统版本上面的实现方式不尽相同,主要有以下实现方式:

1、select:
select库是在linux和windows平台都基本支持的 事件驱动模型库,并且在接口的定义也基本相同,只是部
分参数的含义略有差异,最大并发限制1024,是最早期的事件驱动模型。
2、poll:
在Linux 的基本驱动模型,windows不支持此驱动模型,是select的升级版,取消了最大的并发限制,在编
译nginx的时候可以使用--with-poll_module和--without-poll_module这两个指定是否编译select
库。
3、epoll:
epoll是库是Nginx服务器支持的最高性能的事件驱动库之一,是公认的非常优秀的事件驱动模型,它和
select和poll有很大的区别,epoll是poll的升级版,但是与poll有很大的区别.
epoll的处理方式是创建一个待处理的事件列表,然后把这个列表发给内核,返回的时候在去轮训检查这个
表,以判断事件是否发生,epoll支持一个进程打开的最大事件描述符的上限是系统可以打开的文件的最大
数,同时epoll库的I/O效率不随描述符数目增加而线性下降,因为它只会对内核上报的“活跃”的描述符进行
操作。
4、rtsig:
不是一个常用事件驱动,最大队列1024,不是很常用
5、kqueue:
用于支持BSD系列平台的高校事件驱动模型,主要用在FreeBSD 4.1及以上版本、OpenBSD 2.0级以上版
本,NetBSD级以上版本及Mac OS X 平台上,该模型也是poll库的变种,因此和epoll没有本质上的区别,
都是通过避免轮训操作提供效率。
6、/dev/poll:
用于支持unix衍生平台的高效事件驱动模型,主要在Solaris 平台、HP/UX,该模型是sun公司在开发
Solaris系列平台的时候提出的用于完成事件驱动机制的方案,它使用了虚拟的/dev/poll设备,开发人员
将要见识的文件描述符加入这个设备,然后通过ioctl()调用来获取事件通知,因此运行在以上系列平台的时
候请使用/dev/poll事件驱动机制。
7、eventport:
该方案也是sun公司在开发Solaris的时候提出的事件驱动库,只是Solaris 10以上的版本,该驱动库看防
止内核崩溃等情况的发生。
8、Iocp:
 Windows系统上的实现方式,对应第5种(异步I/O)模型。

 二、Nginx概述

2.1 Nginx架构

2.2 Nginx进程架构

web请求处理机制

  • 多进程方式:服务器每接收到一个客户端请求就有服务器的主进程生成一个子进程响应客户端,直到用户关闭连接,这样的优势是处理速度快,子进程之间相互独立,但是如果访问过大会导致服务器资源耗尽而无法提供请求。

  • 多线程方式:与多进程方式类似,但是每收到一个客户端请求会有服务进程派生出一个线程来个客户方进行交互,一个线程的开销远远小于一个进程,因此多线程方式在很大程度减轻了web服务器对系统资源的要求,但是多线程也有自己的缺点,即当多个线程位于同一个进程内工作的时候,可以相互访问同样的内存地址空间,所以他们相互影响,一旦主进程挂掉则所有子线程都不能工作了,IIS服务器使用了多线程的方式,需要间隔一段时间就重启一次才能稳定。

主进程(master process)的功能:

对外接口:接收外部的操作(信号)
对内转发:根据外部的操作的不同,通过信号管理 Worker
监控:监控 worker 进程的运行状态,worker 进程异常终止后,自动重启 worker 进程
读取Nginx 配置文件并验证其有效性和正确性
建立、绑定和关闭socket连接
按照配置生成、管理和结束工作进程
接受外界指令,比如重启、升级及退出服务器等指令
不中断服务,实现平滑升级,重启服务并应用新的配置
开启日志文件,获取文件描述符
不中断服务,实现平滑升级,升级失败进行回滚处理
编译和处理perl脚本

工作进程(worker process)的功能:

所有 Worker 进程都是平等的
实际处理:网络请求,由 Worker 进程处理
Worker进程数量:一般设置为核心数,充分利用CPU资源,同时避免进程数量过多,导致进程竞争CPU资源,
增加上下文切换的损耗
接受处理客户的请求
将请求依次送入各个功能模块进行处理
I/O调用,获取响应数据
与后端服务器通信,接收后端服务器的处理结果
缓存数据,访问缓存索引,查询和调用缓存数据
发送请求结果,响应客户的请求
接收主程序指令,比如重启、升级和退出等

2.3 Nginx模块

  • 核心模块:是 Nginx 服务器正常运行必不可少的模块,提供错误日志记录 、配置文件解析 、事件驱动机制 、进程管理等核心功能

  • 标准HTTP模块:提供 HTTP 协议解析相关的功能,比如: 端口配置 、 网页编码设置 、 HTTP响应头设置 等等

  • 可选HTTP模块:主要用于扩展标准的 HTTP 功能,让 Nginx 能处理一些特殊的服务,比如:Flash 多媒体传输 、解析 GeoIP 请求、 网络传输压缩 、 安全协议 SSL 支持等

  • 邮件服务模块:主要用于支持 Nginx 的 邮件服务 ,包括对 POP3 协议、 IMAP 协议和 SMTP协议的支持

  • Stream服务模块: 实现反向代理功能,包括TCP协议代理 反向

  • 第三方模块:是为了扩展 Nginx 服务器应用,完成开发者自定义功能,比如: Json 支持、 Lua 支持等

常用模块:

ngx_http_core_module         核心模块
ngx_http_access_module       访问控制  
ngx_http_auth_basic_module   身份验证
ngx_http_gzip_module         压缩模块
ngx_http_log_module          日志模块
ngx_http_proxy_module        代理模块
ngx_http_rewrite_module      重写模块
ngx_http_stub_status_module  状态页模块
ngx_http_upstream_module     反向代理
ngx_http_stream_module       四层代理

三、编译安装Nginx

3.1 编译安装Nginx 

yum -y install gcc pcre-devel openssl-devel zlib-devel openssl  openssl-devel
#安装依赖包   
useradd -M -s /sbin/nologin nginx
#新建nginx用户便于管理

cd /opt/
wget http://nginx.org/download/nginx-1.18.0.tar.gz
#官网下载安装包

tar xf nginx-1.18.0.tar.gz 
cd nginx-1.18.0/
#解压软件包
mkdir /apps/nginx -p


./configure --help   
#查看帮助模块

./configure --prefix=/apps/nginx \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module


make    
make install

chown -R nginx.nginx /apps/nginx
#修改权限

ll /apps/nginx/
total 0
drwxr-xr-x 2 root root 333 Sep 22 12:49 conf
drwxr-xr-x 2 root root  40 Sep 22 12:49 html
drwxr-xr-x 2 root root   6 Sep 22 12:49 logs
drwxr-xr-x 2 root root  19 Sep 22 12:49 sbin

######安装好后生成四个文件功能如下
  1. conf:保存nginx所有的配置文件,其中nginx.conf是nginx服务器的最核心最主要的配置文件,其他的.conf则是用来配置nginx相关的功能的,例如fastcgi功能使用的是fastcgi.conf和fastcgi_params两个文件,配置文件一般都有个样板配置文件,是文件名.default结尾,使用的使用将其复制为并将default去掉即可。

  2. html目录中保存了nginx服务器的web文件,但是可以更改为其他目录保存web文件,另外还有一个50x的web文件是默认的错误页面提示页面。

  3. logs:用来保存nginx服务器的访问日志错误日志等日志,logs目录可以放在其他路径,比如/var/logs/nginx里面。

  4. sbin:保存nginx二进制启动脚本,可以接受不同的参数以实现不同的功能。

3.2  创建Service文件

#复制同一版本的nginx的yum安装生成的service文件

vim /usr/lib/systemd/system/nginx.service
#建立文件
[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/apps/nginx/logs/nginx.pid
#注意文件位置,如果不对 启动不了
ExecStart=/apps/nginx/sbin/nginx -c /apps/nginx/conf/nginx.conf
#注意启动文件位置
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
LimitNOFILE=100000

[Install]
WantedBy=multi-user.target


###如果需要修改pid文件可以执行以下操作#################
mkdir /apps/nginx/run/
#创建目录
vim /apps/nginx/conf/nginx.conf
#修改配置文件
pid   /apps/nginx/run/nginx.pid;
#找到 pid的位置修改  
#######################################################


systemctl daemon-reload 
#重新加载配置
systemctl enable --now nginx
#开机自启并立即启动    如果卡主是应为logs下有 nginx.pid  文件  删除即可

chown -R nginx.nginx /apps/nginx
#修改权限

3.3 yum安装

centos7 需要安装epel源
yum install -y epel-release
#安装epel源   额外      rpeo
yum install nginx -y

3.4 平滑升级及命令、信号使用

nginx -h
  -v            : show version and exit
  -V            : show version and configure options then exit
  -t            : test configuration and exit
  -T            : test configuration, dump it and exit
  -q            : suppress non-error messages during configuration testing
  -s signal     : send signal to a master process: stop, quit, reopen, reload
  -p prefix     : set prefix path (default: /etc/nginx/)
  -e filename   : set error log file (default: /var/log/nginx/error.log)
  -c filename   : set configuration file (default: /etc/nginx/nginx.conf)
  -g directives : set global directives out of configuration file

3.4.1 详细显示编译情况信息

nginx -V
nginx version: nginx/1.22.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'

3.4.2 发送信号

kill -l  看信号大全
nginx -h   中可以看到的信号较少
s signal     : send signal to a master process: 
stop, quit, reopen, reload

可以使用man手册来查看详细的信号 如果没安装,去源码包里找到man文件
man   路径/nginx.8      不加路径打不开man帮助
stop      	SIGTERM        直接停止
quit       	SIGQUIT        优雅的退出:有人在访问不会结束进程
reopen   	SIGUSR1        分割日志
reload   	SIGHUP         重新加载配置文件
			SIGHUP           Reload configuration, start the new worker process with a new configuration, and
                             gracefully shut down old worker processes.
     		SIGQUIT          Shut down gracefully.  优雅的关闭:有人在访问不会结束进程
     		SIGUSR1          Reopen log files.       重新分割日志
     		SIGUSR2          Upgrade the nginx executable on the fly.  运行中升级
     		SIGWINCH         Shut down worker processes gracefully.    优雅的关闭worker进程,work进程负责处理请求,还有请求不会关闭
     		
     		
帮助: -? -h
使用指定的配置文件: -c
指定配置指令:-g
指定运行目录:-p
测试配置文件是否有语法错误:-t -T
打印nginx的版本信息、编译信息等:-v -V
发送信号: -s 示例: nginx -s reload

nginx -s   stop   #立即关闭nginx
nginx -s   quit   #优雅退出   不影响业务的状态下退出
nginx -s   reload #重新加载
nginx -t          #检查语法格式
cd /var/log/nginx/
#切换到
mv access.log access.log.bak
touch access.log

#此时日志不会写入到新文件

需要给master 进程发送  USR1信号
ps aux |grep nginx

root     117994  0.0  0.0  49024  1084 ?        Ss   11:23   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx    117995  0.0  0.0  51512  2156 ?        S    11:23   0:00 nginx: worker process
nginx    117996  0.0  0.0  51512  1932 ?        S    11:23   0:00 nginx: worker process
root     120458  0.0  0.1 151664  5048 pts/1    S+   12:32   0:00 vim /usr/lib/systemd/system/nginx.serv


kill   -s  USR1 117994
#kill是要跟进程
nginx  -s  reopen 
#nginx -s  不能跟进程

3.4.3 飞行升级

飞行升级过程:

  1. 1.将旧Nginx文件换成新Nginx文件(注意备份)

  2. 2.向master进程发送USR2信号

  3. 3.master进程修改pid文件名,加后缀.oldbin

  4. 4.master进程用新Nginx文件启动新master进程,系统中将有新旧两个Nginx主进程共同提供Web服务

  5. 5.向旧的Nginx服务进程发送WINCH信号,使旧的Nginx worker进程平滑停止,并删除Nginx.pid.oldbin文件

  6. 6.向旧master进程发送QUIT信号,关闭老master

  7. 7.如果发现升级有问题,可以回滚向老master发送HUP,向新master发送QUIT

同样将新版本的nginx包进行编译安装

tar zxvf nginx-xxx

cd nginx-xxx

.configure 安装参数与之前基本一致,需要添加新功能往后添加即可

make    #make后不要执行make install

将旧版本的nginx主程序名称改名为nginx.bak

obis/nginx -v    #查看版本

cp objs/nginx/apps/nginx/sbin/    #将新版本拷入

kill -USER2 `cat /apps/nginx/run/nginx.pid`
#发送2信号,信号在man手册中可以看到

四、配置Nginx

 Nginx的配置文件的组成部分:

  • 主配置文件:nginx/conf/nginx.conf
  • 子配置文件:nginx/conf.d/*.conf
配置文件由指令和指令块构成
每条指令以;分号结尾,指令与值之间以空格符号分隔
pid    /apps/run/nginx.pid
指令已{}达括号将多条指令组织在一起且可以嵌套指令块
include语句允许组合多个配置文件以提升可维护性 
#号注释
$使用变量
部分支持正则
自定义变量:由用户使用set命令定义,格式: set variable_name value



全局配置
events{  控制事件驱动      }
http  {  web网页配置有关   server  { location  }   }

main block:主配置段,即全局配置段,对http,mail都有效

#事件驱动相关的配置   同步
event {
 ...
}   
#http/https 协议相关配置段
http {
 ...
}          
#默认配置文件不包括下面两个块
#mail 协议相关配置段
mail {
 ...
}    
#stream 服务器相关配置段
stream {负载均衡
 ...
}

4.1 全局配置

4.1.1 关闭版本或修改版本

Syntax:server_tokens on | off | build | string;
Default:
server_tokens on;
Context:http, server, location
​
#修改配置文件 放在   http语句中
http {
  server_tokens off;
   
​
​
[root@localhost nginx]#nginx -s reload
#重新加载
​
验证
[root@localhost sbin]#curl -I http://192.168.91.100/
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Thu, 21 Apr 2022 03:34:51 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 19 Apr 2022 02:43:17 GMT
Connection: keep-alive
ETag: "625e21c5-264"
Accept-Ranges: bytes
​
[root@localhost sbin]#curl -I http://192.168.91.100/
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 21 Apr 2022 04:04:23 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 19 Apr 2022 02:43:17 GMT
Connection: keep-alive
ETag: "625e21c5-264"
Accept-Ranges: bytes
​
自行修改

#去修改源码,在安装包里, 再重新编译 #号不要去掉
#先吧服务关闭,不然编译不成功
​
[root@localhost core]#vim /opt/nginx-1.18.0/src/core/nginx.h
13 #define NGINX_VERSION     "9527"
14 #define NGINX_VER         "http/" NGINX_VERSION
​
[root@localhost core]#vim /opt/nginx-1.18.0/src/http/ngx_http_header_filter_module.c 
49 static u_char ngx_http_server_string[] = "Server: kgc" CRLF;
​
​
重新编译安装
./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
​
[root@localhost nginx-1.18.0]#make && make install

4.1.2 修改启动的进程数

worker_processes  1;   
#允许的启动工作进程数数量,和你真实的cpu数量有关   1
​
worker_processes auto;
#如果设置为auto 就是你真实的cpu数量
​
​
​
[root@localhost ~]#ps axo pid,cmd,psr,ni|grep nginx
#可以看到 nginx的 worker数量
18620 nginx: master process /usr/   0   0
18621 nginx: worker process         2   0
18622 nginx: worker process         3   0
18623 nginx: worker process         0   0
18624 nginx: worker process         3   0
18641 grep --color=auto nginx       0   0

4.1.3 cpu与work 进程绑定

将Nginx工作进程绑定到指定的CPU核心,默认Nginx是不进行进程绑定的,绑定并不是意味着当前nginx进程独占以一核心CPU,但是可以保证此进程不会运行在其他核心上,这就极大减少了nginx的工作进程在不同的cpu核心上的来回跳转,减少了CPU对进程的资源分配与回收以及内存管理等,因此可以有效的提升nginx服务器的性能。

CPU序号:
CPU MASK: 00000001:0号CPU
          00000010:1号CPU
          ................
          10000000:7号CPU
worker_cpu_affinity 00000001 00000010 00000100 00001000;第0号---第3号CPU   
#序号绑定cpu   亲缘性
worker_cpu_affinity 00000101 00001010;
#同一个work 可以绑定 两个cpu可以这么写 但是不建议,本来就是 不希望飘动,这样也是飘动
​
​
实际操作
例子:
user nginx;
worker_processes auto;
worker_cpu_affinity 00000001 00000010;
#绑定到 第一 和 第二块cpu上
error_log /var/log/nginx/error.log;
#注意 要绑一起绑
​
​
​
​
[root@localhost ~]#ps axo pid,cmd,psr,ni|grep -v grep |grep nginx|sort -n
18620 nginx: master process /usr/   2   0
18951 nginx: worker process         0   0
18952 nginx: worker process         1   0
18954 grep --color=auto nginx       2   0


验证cpu乱跑可以刷新网页即可
while true ;do ab -c 1000 -n 1000 http://192.168.91.100/;done

4.1.4 PID 路径

pid   /apps/nginx/run/nginx.pid;
​
​
pid 进程号文件位置可以自定义省略

4.1.5 nginx进程的优先级(work进程的优先级)

当你想将nginx的work进程的优先级调高 可以使用nice设置

nice的优先级是  -20 到 19
​
worker_priority 0; 
#工作进程优先级,-20~20(19)​
​
[root@localhost ~]#ps axo pid,cmd,psr,ni|grep nginx|sort -n
#查看默认优先级,默认优先级为0
18620 nginx: master process /usr/   3   0
19045 nginx: worker process         0   0
19046 nginx: worker process         1   0
19082 vim /etc/nginx/nginx.conf     1   0
19173 grep --color=auto nginx       1   0
​
修改配置文件
user nginx;
worker_processes 2;
worker_cpu_affinity 00000101 00000010;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
worker_priority -20;
#添加此项
nginx -s reload
​
​
​
[root@localhost ~]#ps axo pid,cmd,psr,ni|grep nginx|sort -n
18620 nginx: master process /usr/   3   0
19196 nginx: worker process         0 -20
19197 nginx: worker process         1 -20
19199 grep --color=auto nginx       1   0
​

4.1.6 调试work进程打开的文件的个数

pid /run/nginx.pid;
worker_priority -20;
worker_rlimit_nofile 65536; 
#所有worker进程能打开的文件数量上限,包括:Nginx的所有连接(例如与代理服务器的连接等),而不仅仅是与客户端的连接,另一个考虑因素是实际的并发连接数不能超过系统级别的最大打开文件数的限制.最好与ulimit -n 或者limits.conf的值保持一致,
​
只要机器性能够多加几个也没问题
​
​
例子:
​
[root@localhost ~]#ps axo pid,cmd,psr,ni|grep nginx|sort -n
18620 nginx: master process /usr/   0   0
19302 nginx: worker process         0 -20
19303 nginx: worker process         1 -20
19456 grep --color=auto nginx       0   0
#选择其中一个进程   到proc 下去查看 连接状态
​
[root@localhost ~]#ls /proc/19302/fd
#可以看到打开的连接数
0  1  10  13  14  15  2  4  5  6  7  9
​
​
在站点目录下生成大文件big.img
[root@localhost ~]#cd /usr/share/nginx/html/
[root@localhost ~]#dd if=/dev/zero of=big.img bs=100M count=1
​
​
可以在 2号机器上安装压力测试的工具写一个压力测试脚本
[root@localhost ~]#yum install httpd-tools -y
#安装压力测试的工具
[root@localhost ~]#while : ;do ab -c 1000 -n 10000 http://192.168.91.100/big.img;sleep 1;done
#写一个压力测试脚本
​
​
回到1号机器
[root@localhost ~]#ls /proc/19302/fd
#在2号机压力测试后 就会产生很多 进程文件
0    137  176  214  253  292  330  37   408  447  486  524  563  601  640  68
1    138  177  215  254  293  331  370  409  448  487  525  564  602  641  680
10   139  178  216  255  294  332  371  41   449  488  526  565  603  642  681
100  14   179  217  256  295  333  372  410  45   489  527  566  604  643  69
101  140  18   218  257  296  334  373  411  450  49   528  567  605  644  7
​
​
​
​
改了后还需要 修改 系统默认项
​
​
[root@localhost ~]#ulimit -a
#单个进程能打开的文件是1024
core file size         (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 7168
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                     (-n) 1024
pipe size           (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority             (-r) 0
stack size             (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes             (-u) 7168
virtual memory         (kbytes, -v) unlimited
file locks                     (-x) unlimited
​
[root@localhost ~]#ulimit -n 60000
#只修改当前窗口
​
需要修改pam认证文件
[root@localhost ~]#vim /etc/security/limits.conf 
#最后加入
​
*               soft   core           unlimited
*               hard   core           unlimited
*               soft   nproc           1000000
*               hard   nproc           1000000
*               soft   nofile          1000000
*               hard   nofile          1000000
*               soft   memlock         32000
*               hard   memlock         32000
*               soft   msgqueue        8192000
*               hard   msgqueue        8192000
​
​
#设置完后重启
[root@localhost ~]#ulimit -a
core file size         (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 7168
max locked memory       (kbytes, -l) 32000
max memory size         (kbytes, -m) unlimited
open files                     (-n) 1000000
pipe size           (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 8192000
real-time priority             (-r) 0
stack size             (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes             (-u) 1000000
virtual memory         (kbytes, -v) unlimited
file locks                     (-x) unlimited

4.1.7 服务是否已后台方式运行

一般服务都是后台运行,前台容器中会用到

user nginx;
worker_processes 2;
worker_cpu_affinity 00000101 00000010;
daemon off;
#加入此选项
​
​
[root@localhost ~]#systemctl start nginx

4.1.8 只有 master进程没有 work进程

实际生产中使用较少

master_process off|on;
#是否开启Nginx的master-worker工作模式,仅用于开发调试场景,默认为on

4.2 event事件

events {
   worker_connections  65536;  #设置单个工作进程的最大并发连接数
   use epoll;
   #使用epoll事件驱动,Nginx支持众多的事件驱动,比如:select、poll、epoll,只能设置在events模块中设置。
   accept_mutex on; 
   #on为同一时刻一个请求轮流由work进程处理,而防止被同时唤醒所有worker,避免多个睡眠进程被唤醒的设置,默认为off,新请求会唤醒所有worker进程,此过程也称为"惊群",因此nginx刚安装完以后要进行适当的优化。建议设置为on
   multi_accept on; 
   #ON时Nginx服务器的每个工作进程可以同时接受多个新的网络连接,此指令默认为off,即默认为一个工作进程只能一次接受一个新的网络连接,打开后几个同时接受多个。建议设置为on
}

4.3 http模块

http 是一个大的语句块,包含若干个小的语句块(比如server语句块)

http {
 ...
 ...  #各server的公共配置
 server {    #每个server用于定义一个虚拟主机,第一个server为默认虚拟服务器
 ...
 }
 server {     
 ...
 server_name   #虚拟主机名
 root     #主目录
 alias     #路径别名
 location [OPERATOR] URL {     #指定URL的特性
 ...
 if CONDITION {
 ...
 }
 }
 }
}

http 协议配置说明

http {
   include       mime.types; #导入支持的文件类型,是相对于/apps/nginx/conf的目录
   default_type application/octet-stream; #除mime.types中文件类型外,设置其它文件默认类型,访问其它类型时会提示下载不匹配的类型文件
#日志配置部分
    #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; #在开启了sendfile的情况下,合并请求后统一发送给客户端。
    #tcp_nodelay   off; #在开启了keepalived模式下的连接是否启用TCP_NODELAY选项,当为off时,延迟0.2s发送,默认On时,不延迟发送,立即发送用户响应报文。
    #keepalive_timeout 0;
   keepalive_timeout  65 65; #设置会话保持时间,第二个值为响应首部:keepAlived:timeout=65,可以和第一个值不同
    #gzip on; #开启文件压缩,无法压缩图片
   server {
       listen       80; #设置监听地址和端口
       server_name localhost; #设置server name,可以以空格隔开写多个并支持正则表达式,如:*.kgc.com www.kgc.* ~^www\d+\.kgc\.com$ default_server 
        #charset koi8-r; #设置编码格式,默认是俄语格式,建议改为utf-8
        #access_log logs/host.access.log main;
       location /fxj  {           www.ky31.com/fsj     /apps/nginx/html   
           root   /data;
           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;
       }
        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ { #以http的方式转发php请求到指定web服务器
        #   proxy_pass   http://127.0.0.1;
        #}
        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ { #以fastcgi的方式转发php请求到php处理
        #   root           html;
        #   fastcgi_pass   127.0.0.1:9000;
        #   fastcgi_index index.php;
        #   fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
        #   include       fastcgi_params;
        #}
        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht { #拒绝web形式访问指定文件,如很多的网站都是通过.htaccess文件
来改变自己的重定向等功能。
        #   deny all;
        #}
       location ~ /passwd.html {
           deny all;
       }
   }
    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server { #自定义虚拟server
3.3.1 MIME
范例: 识别php文件为text/html
    #   listen       8000;
    #   listen       somename:8080;
    #   server_name somename alias another.alias;
    #   location / { 
    #       root   html;
    #       index index.html index.htm; #指定默认网页文件,此指令由
ngx_http_index_module模块提供
    #   }
    #}
    # HTTPS server
    #
    #server { #https服务器配置
    #   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;
    #       index index.html index.htm;
    #   }
    #}

4.3.1 mime

此项为支持的文件格式,如果不支持的格式会自动帮你下载,如果支持就会显示在网页上 

vim  /etc/nginx/mime.types
types {
    text/html                                        html htm shtml;
    .....................................................................
    image/png                                        png;
    image/svg+xml                                    svg svgz;
    image/tiff                                       tif tiff;
    image/vnd.wap.wbmp                               wbmp;
    image/webp                                       webp;
    image/x-icon                                     ico;
    image/x-jng                                      jng;
    image/x-ms-bmp                                   bmp;

4.3.2 server下的root

root用于指定主页文件的位置,即主站点

root路径格式 指定文件的路径    url  
Syntax:	root path;
Default:	
root html;
Context:	http, server, location, 

指明  你软件的根目录

 4.3.3 server块构建虚拟主机

A 建立独立的配置文件 构建不同虚拟主机 PC端和手机端

[root@localhost ~]#vim /etc/nginx/nginx.conf
#修改配置文件 要放在  http 模块里
 include             /etc/nginx/mime.types;
 include             /apps/nginx/conf.d/*.conf;

[root@localhost ~]#mkdir -p /apps/nginx/conf.d/
#建立子配置文件

[root@localhost conf.d]#vim pc.conf 
#分别编写配置文件
server {
   listen 80;
   server_name localhost;
   root /data/nginx/html/pc/;
}
#也可以使用location  模块
server{
        listen   192.168.91.100:80;
        server_name www.pc.com;
     location / {
        root  /data/nginx/html/pc;
    }
}


[root@localhost conf.d]#vim mobile.conf 
#分别编写配置文件
server {
   listen 80;
   server_name m.kgc.com;
   root /data/nginx/html/mobile/;
}



[root@localhost ~]#mkdir /data/nginx/html/pc -pv
[root@localhost ~]#mkdir /data/nginx/html/mobile -pv
#构建数据文件夹

[root@localhost ~]#echo pc > /data/nginx/html/pc/index.html
[root@localhost ~]#echo moblie > /data/nginx/html/mobile/index.html
#构建数据文件



####################################################################

去第二台机器修改/etc/hosts 文件
[root@localhost ~]#vim /etc/hosts
192.168.91.100 www.kgc.com
192.168.91.100 m.kgc.com
                        
[root@localhost ~]#curl m.kgc.com
moblie
[root@localhost ~]#curl www.kgc.com
pc


[root@localhost pc]#vim /apps/nginx/conf.d/pc.conf 
server {
   listen 80;
   server_name www.kgc.com;
   location  /admin {
        root /data/nginx/html/pc/;
        }
}


基于端口
server{
        listen 192.168.91.100:8080;
        server_name www.m.com;
        root /data/nginx/html/m;

}

server{
        listen   192.168.91.100:80;
        server_name www.pc.com;
        root  /data/nginx/html/pc;
}


基于不同ip地址

4.3.4 alias别名

用于将匹配的url进行更换

server {
   listen 80;
   server_name www.kgc.com;
   location /nwes {
        root /data/nginx/html/pc/;
        #相当于追加  将 文件夹news追加到/data/nginx/html/pc/news
        }
   location /study{
        alias /mnt/nginx/sports/;
        #相当于替换 你访问 study  就是访问/mnt/nginx/sports
        }
}

4.3.5 location匹配

语法规则

location [ = | ~ | ~* | ^~ ] uri { ... }

=              	#用于标准url前,需要请求字串与uri精确匹配,大小敏感,如果匹配成功就停止向下匹配并立即处理请求
^~            	#用于标准url前,表示包含正则表达式,并且匹配以指定的正则表达式开头,对URI的最左边部分做匹配检查,不区分字符大小写
~              	#用于标准url前,表示包含正则表达式,并且区分大小写
~*            	#用于标准url前,表示包含正则表达式,并且不区分大写
不带符号   	  	#匹配起始于此uri的所有的uri

#\            	#用于标准url前,表示包含正则表达式并且转义字符。可以将 . * ?等转义为普通符号

#匹配优先级从高到低:
=, ^~, ~/~*, 不带符号

www.baidu.com


location = / {
   [ configuration A ]
}

location / {
   [ configuration B ]
}

location /documents/ {
   [ configuration C ]
}
location ^~ /images/ {
   [ configuration D ]
}
location ~* \.(gif|jpg|jpeg)$ {
   [ configuration E ]
}
www.baidu.com/documents/1.jpg

访问路径是    /      A                  
访问路径是    /index.html   B
访问路径是    /documents/document.html      C
访问路径是    /images/1.gif        D
访问路径是    /documents/1.jpg    C

匹配规则

前缀匹配: =、^~、无符号

优先看这三个,
若=匹配上了直接结束,
否则看^~和无符号谁长,若一样长直接^~,若无符号长则先记下来,开始进入下面的正则匹配

正则匹配:~、~*

匹配正则匹配,若没有满足的正则,则以无符号结束

匹配示例

url   192.168.91.100/Test1
优先遍历 筛选出符合条件的前缀匹配
因为F精确匹配    E无符号短前缀匹配 
由于优先级的关系所以
优先匹配F    F =精确匹配!

url  192.168.91.100/Test1/
优先遍历 筛选出符合条件的前缀匹配
C 停止正则表达式匹配  ^~    /Test1/
E 无符号短前缀匹配         /Test1
nginx  会优先遍历CE
CE 优先匹配  C 比 E长  所以选C
E 又会停止匹配正则的location 所以A B出局 
优先匹配  C    停止正则表达式匹配

url  192.168.91.100/Test1/Test2
优先遍历 筛选出符合条件的前缀匹配
C 停止正则表达式匹配     ^~ /Test1/ 
D 无符号最长的前缀匹配   /Test1/Test2
E 无符号短前缀匹配      /Test1 
此时 D  由于最长胜出  但是 由于没有 ^~  前缀 所以会继续按配置文件的顺序去找正则匹配
A ~     /Test1/$   已Test1 结尾显然不符合
B ~*   /Test1/(\w+)$  TEST1后面有1个以上  字母或数字或下划线或汉字   符合要求所以选择   B
优先匹配  B长正则表达式匹配


url  192.168.91.100/Test1/Test2/
优先遍历符合条件的前缀匹配
C 停止正则表达式匹配   ^~ /Test1
D 无符号最长的前缀匹配 /Test1/Test2
E 无符号短前缀匹配    /Test1
先记住 D 无符号最长的前缀匹配
然后去匹配正则
A ~     /Test1/$   已Test1 结尾显然不符合 
B ~*   /Test1/(\w+)$  TEST1后面有1个以上字符  \w #匹配字母或数字或下划线或汉字  而/ 不在w中不符合要求

所以返回优先使用D    无符号最长的前缀匹配


url  192.168.91.100/test1/Test2
优先遍历符合条件的匹配
无前缀符号
直接去匹配正则
只有 B 不区分大小写的正则可以匹配
B ~*   /Test1/(\w+)$  TEST1后面有1个以上字符  \w #匹配字母或数字或下划线或汉字  而/ 不在w中不符合要求
优先匹配B 

原理图

4.3.6 access模块(四层控制)

两种方式:用户名密码方式与匹配IP地址方式

location / {
    deny  192.168.1.1;
    allow 192.168.1.0/24;
    allow 10.1.1.0/16;
    allow 2001:0db8::/32;
    deny  all;
}

配置文件修改
server {
   listen 80;
   server_name www.kgc.com;
   allow 192.168.91.0/24;
   deny 192.168.91.101;
   location / {
        root /data/nginx/html/pc;
 }
}

匹配了之后就不往下匹配了
所以范围小的往上

################################################
当访问 有问题时   默认站点 是按 文件的名字首字母开头排序

 4.3.7 验证模块

配置
server {
   listen 80;
   server_name www.kgc.com;
   location / {
        root /data/nginx/html/pc;
 }
   location /admin{
        root /data/nginx/html/pc;
        auth_basic    "admin site";
        #提示信息,不是所有浏览器都有用
        auth_basic_user_file/apps/nginx/conf.d/.httpuser;
        #密码文件存放位置
 }
}

htpasswd

此命令来自于 httpd-tools 包,如果没有安装 一下即可

使用方法:

第一次生成文件
htpasswd -c  文件路径 姓名        	 交互式生成密码
htpasswd -bc 文件路径 姓名 密码   		直接将密码跟在后面 

-c  代表新建用户名和密码对应的文件
-b  将密码跟在用户名后

非第一次
htpasswd     文件路径 姓名        	 交互式生成密码
htpasswd -b  文件路径 姓名 密码   		直接将密码跟在后面 

第一次
[root@localhost conf.d]#htpasswd -bc /apps/nginx/conf.d/.httpuser kgc 123456
#没有  yum install  httpd-tools    -b  将名字密码跟在后面    -c  新建文件
Adding password for user kgc
[root@localhost conf.d]#cat /apps/nginx/conf.d/.httpuser 
kgc:$apr1$RtjFE23R$lf2n.YpdssSf1EYJbIDqT0

非第一次
[root@localhost error]#htpasswd /apps/nginx/conf.d/.httpuser xiaoming
New password: 
Re-type new password: 
Adding password for user xiaoming

4.3.8 自定义错误页面

可以改变默认的错误页面,同时也可以用指定的响应状态码进行响应

可用位置:http, server, location, if in location

格式:

error_page code ... [=[response]] uri;
页面错误代码  
error_page    固定写法
code          响应码
=             可以将响应码转换
response			code状态码,可自定义,如666、888
uri           访问连接

实际操作:

www.pc.com/xxxxxxxx                   404
www.pc.com/40x.html
server {
   listen 80;
   server_name www.kgc.com;
   root /data/nginx/html/pc;
   error_page 404 /40x.html;
   #当出现404 错误  就去  root /data/nginx/html/pc/error/ 这个文件夹找40x.html  这个文件
   location = /40x.html {
        root /data/nginx/html/pc/error/;
 }
   location / {
        root /data/nginx/html/pc;
 }
   location /admin{
        auth_basic    "admin site";
        auth_basic_user_file /apps/nginx/conf.d/.httpuser;
 }
}
[root@localhost nginx]#mkdir /data/nginx/html/pc/error/
#建立目录
[root@localhost nginx]#cd  /data/nginx/html/pc/error/
#切换目录
[root@localhost nginx]#vim   40x.html
#新建页面,此处页面名字需要和 配置文件中的一致


自定义 错误码
server {
   listen 80;
   server_name www.kgc.com;
   root /data/nginx/html/pc;
   error_page 404 =302 /40x.html;
   #把错误码 404 指定成302    注意此处的  40x.html 需要真实存在建立的页面必须一致
   location = /40x.html {
        root /data/nginx/html/pc/error/;
 }
   location / {
        root /data/nginx/html/pc;
 }
   location /admin{
        auth_basic    "admin site";
        auth_basic_user_file /apps/nginx/conf.d/.httpuser;
 }
}


#出了错  直接跳转到显示主站点
server {
   listen 80;
   server_name www.kgc.com;
   root /data/nginx/html/pc;
   error_page 404 =302 /index.html;
   #把错误码 404 指定成302  并跳到主页面:/index.html

4.3.9 日志位置存放

#格式
Syntax: error_log file [level];
error_log    /apps/nginx/logs/kgc_error.log;
固定格式      文件路径                         级别(info  debug等  可以忽略不写)
      

Default: 
error_log logs/error.log error;
Context: main, http, mail, stream, server, location
level: debug, info, notice, warn, error, crit, alert, emerg



[root@centos7 ~]# mkdir /data/nginx/logs
 listen 80;
 server_name www.kgc.org;
 error_page  500 502 503 504 404 /error.html; 
 access_log /apps/nginx/logs/kgc_access.log; 
 error_log /apps/nginx/logs/kgc_error.log; 
 #定义错误日志文件


#重启nginx并访问不存在的页面进行测试并验证是在指定目录生成新的日志文件


[root@localhost ~]#mkdir /apps/nginx/logs
[root@localhost ~]#nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@localhost ~]#nginx -s reload

实际操作,将两个网站的日志分离

[root@localhost error]#vim /apps/nginx/conf.d/m.conf
server{
        listen 80;
        server_name  www.m.com;
        root /data/nginx/m/;
        error_log    /data/logs/m_error.log;
        access_log  /data/logs/m_access.log;
}


[root@localhost error]#vim /apps/nginx/conf.d/pc.conf
server{
        listen 80;
        server_name  www.pc.com;
        root /data/nginx/pc;
        error_log    /data/logs/pc_error.log;
        access_log  /data/logs/pc_access.log;
}
[root@localhost error]#mkdir /data/logs
[root@localhost error]#nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@localhost error]#nginx -s reload

查看日志是否生效

4.3.10 检测文件是否存在

try_files会按顺序检查文件是否存在,返回第一个找到的文件或文件夹(结尾加斜线表示为文件夹),如果所有文件或文件夹都找不到,会进行一个内部重定向到最后一个参数。只有最后一个参数可以引起一个内部重定向,之前的参数只设置内部URI的指向。最后一个参数是回退URI且必须存在,否则会出现内部500错误。

语法格式

Syntax: try_files file ... uri;
try_files file ... =code;
Default: —
Context: server, location

www.baidu.com/test

例子

location / {
   root /data/nginx/html/pc;
   try_files $uri  $uri.html $uri/index.html /about/default.html;
    #try_files $uri $uri/index.html $uri.html =489;
}

www.pc.com/abc       
我的访问是路径下的abc文件,那按照设置,先会去找abc,没有abc会在后面加上abc.html,再没有会在路径后补上abc/index.html
最后没有会有一个兜底的




[root@centos8 ~]# echo "default page" >> /data/nginx/html/pc/about/default.html
#重启nginx并测试,当访问到http://www.kgc.org/about/xx.html等不存在的uri会显示default.html,如果是自定义的状态码则会显示在返回数据的状态码中
#注释default.html行,启用上面489行生效后,再观察结果
[root@centos8 ~]# curl -I http://www.kgc.org/about/xx.html
HTTP/1.1 489 #489就是自定义的状态返回码
Server: nginx
Date: Thu, 21 Feb 2019 00:11:40 GMT
Content-Length: 0
Connection: keep-alive
Keep-Alive: timeout=65

例子 解释
#一定要有兜底否则也还是报错 我测试的结果   kgc.html是兜底的可能版本不一
location / {
        root /data/nginx/html/pc;
        try_files $uri  $uri.html $uri/index.html /about/default.html;
        #你如果 访问一个路径 /kgc   如果没有这个页面   先去找kgc  kgc.html  然后再去找 kgc/index.html    最后再                           找/about/default.html         
 }

实际操作

[root@localhost pc]#vim /apps/nginx/conf.d/pc.conf
server{
        listen 80;
        server_name  www.pc.com;
        root /data/nginx/pc;
        location  / {
        root      /data/nginx/pc/;
        try_files $uri  $uri.html $uri/index.html /about/default.html;
        }
}


###注意  /about/default.html;      这边的根是  /data/nginx/pc/    下
#所有的文件 都在主目录下  



去第二台机器    
curl   www.pc.com/kgc




#####后面还可以自定义设置返回响应码######
server{
        listen 80;
        server_name  www.pc.com;
        root /data/nginx/pc;
        location  / {
        root      /data/nginx/pc/;
        try_files $uri  $uri.html $uri/index.html =489;
        }
}


########自定义和重新定义页面##############

server{
        listen 80;
        server_name  www.pc.com;
        root /data/nginx/pc;
        location  / {
        root      /data/nginx/pc/;
        try_files $uri  $uri.html $uri/index.html =489;
        }
        error_page 489 /40x.html;
        location = /40x.html {
        root    /data/nginx/error/;
        }
}

4.3.11 长连接

http 基于 tcp 协议 先要 三次握手然后 再传输数据

一次三次握手 下载多个资源

一次三次握手下载一个资源

相关设置

keepalive_timeout timeout [header_timeout];  
#设定保持连接超时时长,0表示禁止长连接,默认为75s,通常配置在http字段作为站点全局配置
keepalive_requests number;  
#在一次长连接上所允许请求的资源的最大数量,默认为100次,建议适当调大,比如:500
可以加在全局或者 server 

例子

keepalive_requests 3;
#最大下载三个资源就会断开
keepalive_timeout 60 65;   #只能有一个空格 
#开启长连接后,返回客户端的会话保持时间为60s,单次长连接累计请求达到指定次数请求或65秒就会被断开,后面的60为发送给客户端应答报文头部中显示的超时时间设置为60s:如不设置客户端将不显示超时时间。
Keep-Alive:timeout=60  #浏览器收到的服务器返回的报文
#如果设置为0表示关闭会话保持功能,将如下显示:
Connection:close  #浏览器收到的服务器返回的报文
#使用命令测试:
[root@centos8 ~]# telnet www.kgc.org 80
Trying 10.0.0.8...
Connected to www.kgc.org.
Escape character is '^]'.
GET / HTTP/1.1
HOST: www.kgc.org



#Response Headers(响应头信息):
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Thu, 24 Sep 2020 04:35:35 GMT
Content-Type: text/html
Content-Length: 7
Last-Modified: Wed, 23 Sep 2020 14:39:21 GMT
Connection: keep-alive
Keep-Alive: timeout=60
ETag: "5c8a6b3a-7"
Accept-Ranges: bytes
#页面内容
pc web

对那种浏览器禁用长连接

keepalive_disable none | browser ...;  
#对哪种浏览器禁用长连接

实际操作

[root@centos8 ~]# telnet www.kgc.org 80
Trying 10.0.0.8...
Connected to www.kgc.org.
Escape character is '^]'.
#请求头
GET / HTTP/1.1                手打
HOST: www.kgc.org             手打   
                              回车

4.3.12 作为下载服务器配置

ngx_http_autoindex_module 模块处理以斜杠字符 "/" 结尾的请求,并生成目录列表,可以做为下载服务

[root@localhost nginx-1.18.0]#./configure --help |grep auto
#自带
  --without-http_autoindex_module    disable ngx_http_autoindex_module
  
autoindex on | off;
#自动文件索引功能,默为off
autoindex_exact_size on | off;  
#计算文件确切大小(单位bytes),off 显示大概大小(单位K、M),默认on
autoindex_localtime on | off ; 
#显示本机时间而非GMT(格林威治)时间,默认off
autoindex_format html | xml | json | jsonp; 
#显示索引的页面文件风格,默认html
limit_rate rate; 
#限制响应客户端传输速率(除GET和HEAD以外的所有方法),单位B/s,即bytes/second,默认值0,表示无限制,此指令由ngx_http_core_module提供
set $limit_rate
#变量提供 限制   变量优先级高

例子

[root@centos8 ~]# mkdir  /opt/download
#注意:download不需要index.html文件


location /download {
       autoindex on;
       #开启下载服务器
       autoindex_exact_size on;
       #开启确切大小不建议开启
       autoindex_localtime on;
       #使用当地时间
       limit_rate 1024k;
       #所有人限速1024k,默认单位是字节数
       set $limit_rate 2M;
       #谁先生效
       alias /opt/download;
  }


直接访问页面
location /download {
       autoindex on;
}

location /download {
       autoindex on;
       autoindex_exact_size on;
       autoindex_localtime on;
       limit_rate 1024k;
       alias /opt/download;
  }

4.3.13 用户上传资料

上传需要借助开发小的程序, 并且程序 5M 和 nginx 10M 都会限制。 两者取最小 

client_max_body_size 1m; 
#设置允许客户端上传单个文件的最大值,默认值为1m,上传文件超过此值会出413错误
client_body_buffer_size size; 
#用于接收每个客户端请求报文的body部分的缓冲区大小;默认16k;超出此大小时,其将被暂存到磁盘上的由下面client_body_temp_path指令所定义的位置
client_body_temp_path path [level1 [level2 [level3]]];
#设定存储客户端请求报文的body部分的临时存储路径及子目录结构和数量,目录名为16进制的数字,使用hash之后的值从后往前截取1位、2位、2位作为目录名

上传文件大于限制  错误代码413

4.3.14 其他设置

directio size | off;
#操作完全和aio相反,aio是读取文件而directio是写文件到磁盘,启用直接I/O,默认为关闭,当文件大于等于给定大小时,例如:directio 4m;同步(直接)写磁盘,而非写缓存。

直接 写入 磁盘     还是等待一定数据量写入磁盘


open_file_cache off;  #是否缓存打开过的文件信息
open_file_cache max=N [inactive=time];
#nginx可以缓存以下三种信息:
(1) 文件元数据:文件的描述符、文件大小和最近一次的修改时间
(2) 打开的目录结构
(3) 没有找到的或者没有权限访问的文件的相关信息 
max=N:#可缓存的缓存项上限数量;达到上限后会使用LRU(Least recently used,最近最少使用)算法实现管理
inactive=time:#缓存项的非活动时长,在此处指定的时长内未被命中的或命中的次数少于



open_file_cache_min_uses    
#指令所指定的次数的缓存项即为非活动项,将被删除 
open_file_cache_valid time; 
#缓存项有效性的检查验证频率,默认值为60s 
open_file_cache_errors on | off; 
#是否缓存查找时发生错误的文件一类的信息,默认值为off
open_file_cache_min_uses number; 
#open_file_cache指令的inactive参数指定的时长内,至少被命中此处指定的次数方可被归类为活动项,默认值为1

范例:
open_file_cache max=10000 inactive=60s; 
#最大缓存10000个文件,非活动数据超时时长60s
open_file_cache_valid   60s;  
#每间隔60s检查一下缓存数据有效性
open_file_cache_min_uses 5; 
#60秒内至少被命中访问5次才被标记为活动数据
open_file_cache_errors   on;
#缓存错误信息



limit_except method ... { ... },仅用于location
#限制客户端使用除了指定的请求方法之外的其它方法 
method:GET, HEAD, POST, PUT, DELETE,MKCOL, COPY, MOVE, OPTIONS, PROPFIND, 
PROPPATCH, LOCK, UNLOCK, PATCH
limit_except GET {
 allow 192.168.91.101;
 deny all;
}
#除了GET和HEAD 之外其它方法仅允许192.168.1.0/24网段主机使用

 五、高级配置

5.1 状态页

基于nginx 模块 ngx_http_stub_status_module 实现,在编译安装nginx的时候需要添加编译参数 --with-http_stub_status_module,否则配置完成之后监测会是提示语法错误注意: 状态页显示的是整个服务器的状态,而非虚拟主机的状态

#配置示例:
location /nginx_status {
   #stub_status;
   auth_basic           "auth login";
   auth_basic_user_file /apps/nginx/conf/.htpasswd;
   allow 192.168.0.0/16;
   allow 127.0.0.1;
   deny all;
 }
 


while : ;do ab -c 1000 -n 10000 http://192.168.91.100/;sleep 1;done
#压力测试  模拟高链接

[root@localhost ~]#curl http://www.kgc.com/nginx_status 2>/dev/null  |awk '/Reading/{print  $2,$4,$6}'
#
[root@localhost ~]#curl http://用户名:密码@www.kgc.com/nginx_status 2>/dev/null  |awk '/Reading/{print  $2,$4,$6}'

#curl http://www.pc.com/status 2> /dev/null |awk '/Reading/{print $2,$4,$6}'


实际操作
只需要添加    location    
location /nginx_status {
   stub_status;
}
 
#状态页用于输出nginx的基本状态信息:
#输出信息示例:
Active connections: 291
server accepts handled requests
 16630948 16630948 31070465
 上面三个数字分别对应accepts,handled,requests三个值
Reading: 6 Writing: 179 Waiting: 106

Active connections: 
#当前处于活动状态的客户端连接数,包括连接等待空闲连接数=reading+writing+waiting
accepts:
#统计总值,Nginx自启动后已经接受的客户端请求的总数。
handled:
#统计总值,Nginx自启动后已经处理完成的客户端请求总数,通常等于accepts,除非有因worker_connections限制等被拒绝的连接
requests:
#统计总值,Nginx自启动后客户端发来的总的请求数。
Reading:
#当前状态,正在读取客户端请求报文首部的连接的连接数,数值越大,说明排队现象严重,性能不足
Writing:
#当前状态,正在向客户端发送响应报文过程中的连接数,数值越大,说明访问量很大
Waiting:
#当前状态,正在等待客户端发出请求的空闲连接数,开启 keep-alive的情况下,这个值等于active – (reading+writing)




##############为了安全考虑#####################
增加验证模块
server{
        listen 80;
        server_name  www.pc.com;
        root  /data/nginx/pc;
location /admin{
        stub_status;
        auth_basic    "admin site";
        auth_basic_user_file /apps/nginx/conf.d/.httpuser;
 }
}

5.2 Nginx第三方模块echo

location  /ip {
  default_type   text/html;
  echo "welcome, your ip addr: ";
  echo $remote_addr;
}

[root@localhost opt]#yum install git -y
#安装git
[root@localhost opt]#git clone https://github.com/openresty/echo-nginx-module.git


./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/opt/echo-nginx-module-master

make && make install

[root@localhost ~]#nginx -t
nginx: [emerg] unknown directive "echo" in /apps/nginx/conf.d/pc.conf:26
nginx: configuration file /apps/nginx/conf/nginx.conf test failed
 
[root@localhost nginx-1.18.0]#ll /apps/nginx/sbin/
总用量 15808
-rwxr-xr-x. 1 root  root  8407568 2月  19 15:35 nginx
-rwxr-xr-x. 1 nginx nginx 7774624 2月  14 17:02 nginx.old


[root@localhost nginx-1.18.0]#nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful

[root@localhost nginx-1.18.0]#systemctl stop nginx
[root@localhost nginx-1.18.0]#systemctl start nginx


location  /hello {
  default_type   text/html;
  echo "hello world ";
}


yum install git -y
cd  /opt
git clone https://github.com/openresty/echo-nginx-module.git
cd   /opt/nginx-1.18.0
./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/opt/echo-nginx-module-master
make -j 2
make install

systemctl  stop nginx
systemctl start nginx

vim /apps/nginx/conf.d/pc.conf
location  /hello {
  default_type   text/html;
  echo "hello world ";
}
第二台机器
curl    www.pc.com/hello

 5.3 变量

5.3.1 内置

$remote_addr; 
#存放了客户端的地址,注意是客户端的公网IP




$proxy_add_x_forwarded_for
#此变量表示将客户端IP追加请求报文中X-Forwarded-For首部字段,多个IP之间用逗号分隔,如果请求中没有X-Forwarded-For,就使用$remote_addrthe “X-Forwarded-For” client request header field with the $remote_addr variable appended to it, separated by a comma. If the “X-Forwarded-For” field is not present in the client request header, the $proxy_add_x_forwarded_for variable is equal to the $remote_addr variable.
客户机    代理1     代理2     nginx服务器
$proxy_add_x_forwarded_for: 在代理1 上存的是  客户机的ip
$proxy_add_x_forwarded_for: 在代理2 上存的是  客户机的ip,代理1的ip            用逗号隔开
$proxy_add_x_forwarded_for: nginx  上存的是  客户机的ip,代理1的ip,代理2的ip



$args; 
#变量中存放了URL中的参数,例如:http://www.kgc.org/main/index.do?id=20190221&partner=search
#返回结果为: id=20190221&partner=search    存放的就是这个

select   *  from table  where id=20190221


$document_root; 
#保存了针对当前资源的请求的系统根目录,例如:/apps/nginx/html



$document_uri;
#保存了当前请求中不包含参数的URI,注意是不包含请求的指令,比
如:http://www.kgc.org/main/index.do?id=20190221&partner=search会被定义为/main/index.do 
#返回结果为:/main/index.do


$host; 
#存放了请求的host名称


limit_rate 10240;
echo $limit_rate;
#如果nginx服务器使用limit_rate配置了显示网络速率,则会显示,如果没有设置, 则显示0


$remote_port; 
#客户端请求Nginx服务器时随机打开的端口,这是每个客户端自己的端口

$remote_user; 
#已经经过Auth Basic Module验证的用户名

$request_body_file; 
#做反向代理时发给后端服务器的本地资源的名称

$request_method; 
#请求资源的方式,GET/PUT/DELETE等

$request_filename; 
#当前请求的资源文件的磁盘路径,由root或alias指令与URI请求生成的文件绝对路径,如:/apps/nginx/html/main/index.html

$request_uri;   https:// www.baidu.com/main/index.do?id=20190221&partner=search 
#包含请求参数的原始URI,不包含主机名,相当于:$document_uri?$args,例如:/main/index.do?id=20190221&partner=search 

$scheme; 
#请求的协议,例如:http,https,ftp等

$server_protocol; 
#保存了客户端请求资源使用的协议的版本,例如:HTTP/1.0,HTTP/1.1,HTTP/2.0等

$server_addr; 
#保存了服务器的IP地址

$server_name; 
#请求的服务器的主机名

$server_port;  443  https 
#请求的服务器的端口号

$http_<name>
#name为任意请求报文首部字段,表示记录请求报文的首部字段
arbitrary request header field; the last part of a variable name is the field name converted to lower case with dashes replaced by underscores 
#用下划线代替横线
#示例: echo $http_User_Agent;  

$http_user_agent; 
#客户端浏览器的详细信息

$http_cookie; 
#客户端的cookie信息


$cookie_<name>
#name为任意请求报文首部字部cookie的key名

$http_<name>
#name为任意请求报文首部字段,表示记录请求报文的首部字段,ame的对应的首部字段名需要为小写,如果有
横线需要替换为下划线
arbitrary request header field; the last part of a variable name is the field 
name converted to lower case with dashes replaced by underscores #用下划线代替横线
#示例: 
echo $http_user_agent; 
echo $http_host;


$sent_http_<name>
#name为响应报文的首部字段,name的对应的首部字段名需要为小写,如果有横线需要替换为下划线,此变量有问题
echo $sent_http_server;



$arg_<name>
#此变量存放了URL中的指定参数,name为请求url中指定的参数
#对比 变量  $arg  是全部, 如果 要id   如下
echo $arg_id;




location /main {
index index.html;
default_type text/html;
echo "hello world,main-->";
echo $remote_addr;
echo $args;
echo $document_root;
echo $document_uri;
echo $host;
echo $http_user_agent;
echo $http_cookie;
echo $request_filename;
echo $scheme;
echo $scheme://$host$document_uri?$args;
}

5.3.2 自定义变量

语法格式:

Syntax: set $variable value;
Default: —
Context: server, location, if

例子:

set $name kgc;
echo $name;
set $my_port $server_port;
echo $my_port;
echo "$server_name:$server_port"; #输出信息如下
[root@centos6 ~]#curl www.kgc.org/main
kgc
80
www.kgc.org:80

######################################################
实际例子:
location /test {
        set $name  kgc;
        echo $name;
        set $my_port $server_port;
        echo $my_port;
        }

5.4 自定义访问日志

5.4.1 日志的格式(可自由指定)

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"'
                      '$server_name:$server_port';


log_format  test  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '	#是否为跳转过来的
                      '"$http_user_agent" "$http_x_forwarded_for"'
                      '$server_name:$server_port';

格式可以定义多个

###注意如果开启 include  注意定义自配置文件与 日志格式的上下关系  ,   日志格式一定要在  include 之前 否则会不生效。

5.4.2 自定义json格式日志

vim   /apps/nginx/conf/nginx.conf

log_format access_json '{"@timestamp":"$time_iso8601",'
        '"host":"$server_addr",'
        '"clientip":"$remote_addr",'
        '"size":$body_bytes_sent,'
        '"responsetime":$request_time,'
        '"upstreamtime":"$upstream_response_time",'
        '"upstreamhost":"$upstream_addr",'  
        '"http_host":"$host",'
        '"uri":"$uri",'
        '"xff":"$http_x_forwarded_for",'
        '"referer":"$http_referer",'
        '"tcp_xff":"$proxy_protocol_addr",'
        '"http_user_agent":"$http_user_agent",'
        '"status":"$status"}';
vim   /apps/nginx/conf.d/pc.conf
location / {
  root /data/nginx/pc/;
  access_log logs/access.log access_json;
}

tail -f    /apps/nginx/logs/access.log
主机2   去访问问     www.pc.com




'"http_user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTMLe/101.0.4951.54 Safari/537.36",'    '"status":"304"}'

cat /var/log/nginx/access.log |sed -r 's/.*(status)":"(.*)"}.*/\2/'

利用脚本分析返回码
[root@localhost ~]#cat /var/log/nginx/access.log |sed -r 's/.*(status)":"(.*)"}.*/\2/'|sort -n|uniq -c
#统计状态码个数
      6 200
     26 304
     28 404


cat /var/log/nginx/access.log |awk -F: '{print $6}'|sed -r 's/"(.*)",.*/\1/'
利用脚本提取ip地址


#!/usr/bin/env python3
#coding:utf-8
status_200= []
status_404= []
with open("access_json.log") as f:
    for line in f.readlines():
        line = eval(line)
        if line.get("status") == "200":
            status_200.append(line.get)
        elif line.get("status") == "404":
            status_404.append(line.get)
        else:
            print("状态码 ERROR")
        print((line.get("clientip")))
f.close()
print("状态码200的有--:",len(status_200))
print("状态码404的有--:",len(status_404))

5.5 Nginx压缩功能

支持对指定类型的文件进行压缩然后再传输给客户端,而且压缩还可以设置压缩比例,压缩后的文件大小将比源文件显著变小,这样有助于降低出口带宽的利用率,降低企业的IT支出,不过会占用相应的CPU资源。Nginx对文件的压缩功能是依赖于模块 ngx_http_gzip_module

配置指令如下:

#启用或禁用gzip压缩,默认关闭
gzip on | off; 

#压缩比由低到高从1到9,默认为1
gzip_comp_level level;

#禁用IE6 gzip功能
gzip_disable "MSIE [1-6]\."; 

#gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k; 

#启用压缩功能时,协议的最小版本,默认HTTP/1.1
gzip_http_version 1.0 | 1.1; 

#指定Nginx服务需要向服务器申请的缓存空间的个数和大小,平台不同,默认:32 4k或者16 8k;
gzip_buffers number size;  

#指明仅对哪些类型的资源执行压缩操作;默认为gzip_types text/html,不用显示指定,否则出错
gzip_types mime-type ...;     

#如果启用压缩,是否在响应报文首部插入“Vary: Accept-Encoding”,一般建议打开
gzip_vary on | off;

#预压缩,先压缩好,不用临时压缩,消耗cpu
gzip_static on | off;


#重启nginx并进行访问测试压缩功能
[root@centos8 ~]# cp /apps/nginx/logs/access.log /data/nginx/html/pc/m.txt
[root@centos8 ~]# echo "test" > /data/nginx/html/pc/test.html #小于1k的文件测试是否会压缩
[root@centos8 ~]# vim /apps/nginx/conf/nginx.conf
gzip on;


gzip_comp_level 5;
gzip_min_length 1k;
gzip_types text/plain application/javascript application/x-javascript text/css 
application/xml text/javascript application/x-httpd-php image/gif image/png;   
gzip_vary on;
#重启Nginx并访问测试:
[root@centos8 ~]# curl --head --compressed 192.168.91.100/test.html
HTTP/1.1 200 OK
Server: nginx
Date: Fri, 22 Feb 2019 01:52:23 GMT
Content-Type: text/html
Last-Modified: Thu, 21 Feb 2019 10:31:18 GMT
Connection: keep-alive
Keep-Alive: timeout=65
Vary: Accept-Encoding
ETag: W/"5c6e7df6-171109"
Content-Encoding: gzip #压缩传输
#验证不压缩访问的文件大小:

实际操作:

server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;
        gzip on;
        gzip_comp_level 9;
        gzip_min_length 1k;
        gzip_vary on;
.................


################开启预压缩##########################
gzip    需要的访问的文件    
        
        
        server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;
        gzip on;
        gzip_comp_level 9;
        gzip_min_length 1k;
        gzip_vary on;
        gzip_static on;            
        
        
        
访问  www.pc.com/文件名 

5.6 https功能(签名证书)

 Web网站的登录页面都是使用https加密传输的,加密数据以保障数据的安全,HTTPS能够加密信息,以免敏感信息被第三方获取,所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议,HTTPS其实是有两部分组成:HTTP + SSL / TLS,也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过TLS进行加密,所以传输的数据都是加密后的数据。

 

1.客户端发起HTTPS请求

用户在浏览器里输入一个https网址,然后连接到服务器的443端口

2.服务端的配置

采用HTTPS协议的服务器必须要有一套数字证书,可以自己制作,也可以向组织申请。区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面。这套证书其实就是一对公钥和私钥

3.传送服务器的证书给客户端

证书里其实就是公钥,并且还包含了很多信息,如证书的颁发机构,过期时间等等

4.客户端解析验证服务器证书

这部分工作是由客户端的TLS来完成的,首先会验证公钥是否有效,比如:颁发机构,过期时间等等,如果发现异常,则会弹出一个警告框,提示证书存在问题。如果证书没有问题,那么就生成一个随机值。然后用证书中公钥对该随机值进行非对称加密

5.客户端将加密信息传送服务器

这部分传送的是用证书加密后的随机值,目的就是让服务端得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值来进行加密解密了

6.服务端解密信息

服务端将客户端发送过来的加密信息用服务器私钥解密后,得到了客户端传过来的随机值

7.服务器加密信息并发送信息

服务器将数据利用随机值进行对称加密,再发送给客户端

8.客户端接收并解密信息

客户端用之前生成的随机值解密服务段传过来的数据,于是获取了解密后的内容

生成私钥证书

第一步先生成 私有CA 机构需要遵守配置文件的要求

vim /etc/pki/tls/openssl.cnf 
[ CA_default ]
dir = /etc/pki/CA # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
#unique_subject = no    # Set to 'no' to allow creation of
                        # several certs with same subject.
new_certs_dir = $dir/newcerts # default place for new certs.
certificate = $dir/cacert.pem # The CA certificate
serial = $dir/serial # The current serial number
crlnumber = $dir/crlnumber # the current crl number
 # must be commented out to leave a V1 CRL
crl = $dir/crl.pem # The current CRL
private_key = $dir/private/cakey.pem# The private key

1、创建CA所需要的文件

#生成证书索引数据库文件
touch /etc/pki/CA/index.txt 
#指定第一个颁发证书的序列号
echo 01 > /etc/pki/CA/serial

2、 生成CA私钥

cd /etc/pki/CA/
(umask 066; openssl genrsa -out private/cakey.pem 2048)
2048  是位数  位数越长越安全

3、生成CA自签名证书

openssl req -new -x509 -key  /etc/pki/CA/private/cakey.pem -days 3650 -out /etc/pki/CA/cacert.pem

选项说明:

-new:生成新证书签署请求
-x509:专用于CA生成自签证书
-key:生成请求时用到的私钥文件
-days n:证书的有效期限
-out /PATH/TO/SOMECERTFILE: 证书的保存路径
openssl x509 -in cacert.pem -noout -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            82:5a:02:66:96:ba:e1:e2
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=cn, ST=js, L=nj, O=kgc, OU=it, CN=www.kgc.com
        Validity
            Not Before: Jun  3 09:30:00 2024 GMT
            Not After : Jun  1 09:30:00 2034 GMT
        Subject: C=cn, ST=js, L=nj, O=kgc, OU=it, CN=www.kgc.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
自动化完成
openssl req -utf8 -newkey rsa:1024 -subj "/CN=www.kgc.org" -keyout app.key -nodes -x509 -out app.crt

自签名证书

[root@localhost certs]#cd  /etc/pki/tls/certs
[root@localhost certs]#make /mnt/www.pc.com.crt
​
​
[root@localhost certs]#ls
ca-bundle.crt  ca-bundle.trust.crt  make-dummy-cert  Makefile  renew-dummy-cert
​
[root@localhost certs]#vim Makefile 
55 %.key:
 56         umask 77 ; \
 57         #/usr/bin/openssl genrsa -aes128 $(KEYLEN) > $@
 58         /usr/bin/openssl genrsa  $(KEYLEN) > $@
​

https参数

ssl on | off;   
#为指定的虚拟主机配置是否启用ssl功能,此功能在1.15.0废弃,使用listen [ssl]替代
listen 443 ssl;

ssl_certificate /path/to/file;
#指向包含当前虚拟主机和CA的两个证书信息的文件,一般是crt文件

ssl_certificate_key /path/to/file;
#当前虚拟主机使用的私钥文件,一般是key文件

ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2]; 
#支持ssl协议版本,早期为ssl现在是TLS,默认为后三个

ssl_session_cache off | none | [builtin[:size]] [shared:name:size];
#配置ssl缓存
 off: #关闭缓存
 none:  #通知客户端支持ssl session cache,但实际不支持
 builtin[:size]:#使用OpenSSL内建缓存,为每worker进程私有
 [shared:name:size]:#在各worker之间使用一个共享的缓存,需要定义一个缓存名称和缓存空间大小,一兆可以存储4000个会话信息,多个虚拟主机可以使用相同的缓存名称

ssl_session_timeout time;
#客户端连接可以复用ssl session cache中缓存的有效时长,默认5m

  自签名证书

#所有的证书需要放在一起不能移开
mkdir ssl
bash certificate.sh   
cat kgc.com.crt ca.crt > www.kgc.com.crt
mv kgc.com.key www.kgc.com.key
ll www.kgc.com*

server{
        listen 80;
        listen 443 ssl;
        ssl_certificate /apps/nginx/conf.d/ssl/www.kgc.com.crt;
        ssl_certificate_key /apps/nginx/conf.d/ssl/www.kgc.com.key;
        ssl_session_cache shared:sslcache:20m;
        ssl_session_timeout 10m;
        server_name www.kgc.com;
        root /data/nginx/pc/;
        gzip on;
        gzip_comp_level 9;
        gzip_min_length 1k;
        gzip_static on;
        location  / {
        root  /apps/nginx/html;
        if ( $scheme = http) {
        rewrite ^/(.*)$ https://www.kgc.com/$1 redirect;
        }
}

5.7 升级openssl

只需要重新编译,加上如下选项即可
./configure  --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/data/echo-nginx-module-master --with-openssl=/data/openssl-1.1.1k

5.8 自定义图标

favicon.ico 文件是浏览器收藏网址时显示的图标,当客户端使用浏览器问页面时,浏览器会自己主动发起请求获取页面的favicon.ico文件,但是当浏览器请求的favicon.ico文件不存在时,服务器会记录404日志,而且浏览器也会显示404报错

#方法一:服务器不记录访问日志:
location = /favicon.ico {
   log_not_found off;
   access_log off;
}
#方法二:将图标保存到指定目录访问:
#location ~ ^/favicon\.ico$ {
location = /favicon.ico {
     root   /data/nginx/html/pc/images;
     expires 365d;  #设置文件过期时间
}



【定制小图标】
wget www.baidu.com/favicon.ico
放到主目录就可以了

不生效可以重新打开浏览器

 六、重写功能rewrite

6.1 rewrite与location的区别

rewrite是在同一域名内更改获取资源的路径

location是对一类路径做控制访问或反向代理,同时还能proxy_pass到其他设备

总结:

rewrite:对访问的域名或者域名内的URL路径地址重写
location:对访问的路径做访问控制或者代理转发

6.2 四个模块指令

6.2.1 if指令

用于条件匹配判断,并根据条件判断结果选择不同的Nginx配置,可以配置在server或location块中进行配置,Nginx的if语法仅能使用if做单次判断,不支持使用if else或者if elif这样的多重判断,用法如下:

if (条件匹配) {   
 action
}

使用正则表达式对变量进行匹配,匹配成功时if指令认为条件为true,否则认为false,变量与表达式之间使用以下符号链接:

= #比较变量和字符串是否相等,相等时if指令认为该条件为true,反之为false
!=  #比较变量和字符串是否不相等,不相等时if指令认为条件为true,反之为false
~ #区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假
!~ #区分大小写字符,判断是否匹配,不满足匹配条件为真,满足匹配条件为假

~* #不区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假
!~* #不区分大小字符,判断是否匹配,满足匹配条件为假,不满足匹配条件为真


-f 和 !-f #判断请求的文件是否存在和是否不存在
-d 和 !-d #判断请求的目录是否存在和是否不存在
-x 和 !-x #判断文件是否可执行和是否不可执行
-e 和 !-e #判断请求的文件或目录是否存在和是否不存在(包括文件,目录,软链接)
#注意:
#如果$变量的值为空字符串或0,则if指令认为该条件为false,其他条件为true。
#nginx 1.0.1之前$变量的值如果以0开头的任意字符串会返回false
#示例:
http://www.baidu.com

3字打头重定向
301  永久重定向  将缓存记录在浏览器中
302  临时重定向  没有缓存  每次都要重定向 
304  


location /main {
     index index.html;
     default_type text/html;
     if ( $scheme = http ){
       echo "if-----> $scheme";
     }
     if ( $scheme = https ){
      echo "if ----> $scheme";
   }
    
     #if (-f $request_filename) {
     #   echo "$request_filename is exist";
     #}
     if (!-e $request_filename) {
        echo "$request_filename is not exist";
        #return ;
   }
 }

http://192.168.91.100/test/a.jpg

/data/test/a.jpg


【用户访问的文件不存在 直接返回主页】
server {
    listen 80;
    server_name www.kgc.com;
    root /data/nginx/pc/;
    location / {
    root /data/nginx/pc/;
}
    location /test {
    default_type text/plain;
    return  301 http://www.baidu.com;
}
    location /main {
    index index.html;
    default_type text/html;
    if ( $scheme = http ){
    return 666 "if-----> $scheme";
   }
    if (!-e $request_filename){
    return 302  /index.html;          #如果用户不存在直接跳转到主页面

}
}
}
www.kgc.com/main/xxxxx     
#注意访问的main下的不存在 目录   
#注意前面的if语句执行后会 停止匹配
【想控制所有网站可以  放到前面】
server {
    listen 80;
    server_name www.kgc.com;
    root /data/nginx/pc/;
    if (!-e $request_filename){
    return 302  /index.html;          #如果用户不存在直接跳转到主页面
	}
	
	location / {
    root /data/nginx/pc/;
}
    location /test {
    default_type text/plain;
    return  301 http://www.baidu.com;
}
    location /main {
    index index.html;
    default_type text/html;
    if ( $scheme = http ){
    return 666 "if-----> $scheme";
   }
    
}
}

6.2.2 return

return用于完成对请求的处理,并直接向客户端返回响应状态码,比如:可以指定重定向URL(对于特殊重定向状态码,301/302等) 或者是指定提示文本内容(对于特殊状态码403/500等),处于此指令后的所有配置都将不被执行,return可以在server、if 和 location块进行配置

语法格式:

www.kgc.com/test/
404
return code; #返回给客户端指定的HTTP状态码
return code [text]; #返回给客户端的状态码及响应报文的实体内容,可以调用变量,其中text如果有空格,需要用单或双引号
return code url; #返回给客户端的URL地址    

return   code  [text] 

 举例:

location / {
   root /data/nginx/html/pc;
    default_type text/html;
   index index.html;
      if ( $scheme = http ){
        #return 666;
        #return 666 "not allow http";
        #return 301 http://www.baidu.com;
       return 500 "service error";
        echo "if-----> $scheme"; #return后面的将不再执行
     }
     if ( $scheme = https ){
      echo "if ----> $scheme";
   }
}
##############################################################
例子1:
server { 
    listen 80;
    server_name www.kgc.com;
    root /data/nginx/pc/;
	location /{
        root /data/nginx/pc/;

}
  location /test {      #访问test 直接返回403
	return 403;         #可以改成666    
  }

}

例子2:
location /test {                #访问test 直接返回403
	return 666 "hello";         #可以改成666自定义,hello是描述 文字可以  图形浏览器不可以    
  }


例子3:
  location /test { 
  default_type text/plain;     #定义文本格式后图形浏览器可以看见
  return 666 "hello";
 } 


例子4:
location /test {
        default_type text/plain;
        return 302 http://www.baidu.com;    
}

location /test {
        default_type text/plain;
        return 301 /index.html;    
}
301 缓存在磁盘上   我们即使关闭nginx  服务器  客户也可以正常跳转      
302 没有缓存 , 服务器断开无法重定向 


301永久重定向
302临时重定向

6.2.3 set指令

指定key并给其定义一个变量,变量可以调用Nginx内置变量赋值给key,另外set定义格式为set $key value,value可以是text, variables和两者的组合。

set   $变量名    变量值 


location /main {
   root /data/nginx/html/pc;
   index index.html;
   default_type text/html;
    set $name kgc;
    echo $name;
    set $my_port $server_port(nginx  自带的变量  服务端口 一般80);
    echo $my_port;
}

6.2.4 break指令

用于中断当前相同作用域(location)中的其他Nginx配置,与该指令处于同一作用域的Nginx配置中,位于它前面的配置生效,位于后面的 ngx_http_rewrite_module 模块中指令就不再执行,Nginx服务器在根据配置处理请求的过程中遇到该指令的时候,回到上一层作用域继续向下读取配置,该指令可以在server块和locationif块中使用

注意: 如果break指令在location块中后续指令还会继续执行,只是不执行 ngx_http_rewrite_module 模块的指令(set rewrit return if),其它指令还会执行

使用语法如下:
if ($slow) {
   limit_rate 10k;
   break;
}
location /main {
   root /data/nginx/html/pc;
   index index.html;
   default_type text/html;
    set $name kgc;
    echo $name;
   break;  #location块中break后面指令还会执行
    set $my_port $server_port;
    echo $my_port;
 }

break之下若有:if、return、rewrite、set指令,则不执行
其他指令继续执行

6.3 rewrite指令

语法格式 :

rewrite regex      replacement(www.baidu.com)   [flag];
正则匹配原始访问url    替代你想让客户访问的           标志  ()permanent301   redirect302  
break last(防止循环)

rewrite只能放在server{},location{},if{}中,

并且默认只能对域名后边的除去传递的参数外的字符串起作用
例如 http://www.kgc.com/abc/bbs/index.php?a=1&b=2 只对/abc/bbs/index.php重写。

 正则表达式格式:

. #匹配除换行符以外的任意字符
\w #匹配字母或数字或下划线或汉字
\s #匹配任意的空白符
\d #匹配数字    [0-9]   
\b #匹配单词的开始或结束
^ #匹配字付串的开始
$ #匹配字符串的结束
* #匹配重复零次或更多次
+ #匹配重复一次或更多次
? #匹配重复零次或一次
(n) #匹配重复n次
{n,} #匹配重复n次或更多次
{n,m} #匹配重复n到m次
*? #匹配重复任意次,但尽可能少重复
+? #匹配重复1次或更多次,但尽可能少重复
?? #匹配重复0次或1次,但尽可能少重复
{n,m}? #匹配重复n到m次,但尽可能少重复
{n,}? #匹配重复n次以上,但尽可能少重复
\W  #匹配任意不是字母,数字,下划线,汉字的字符
\S #匹配任意不是空白符的字符
\D #匹配任意非数字的字符
\B #匹配不是单词开头或结束的位置
[^x] #匹配除了x以外的任意字符
[^kgc] #匹配除了kgc 这几个字母以外的任意字符

  rewrite flag 使用介绍

rewrtie有四种不同的flag,分别是redirect(临时重定向302)、permanent(永久重定向301)、break和last。其中前两种是跳转型的flag,后两种是代理型

  • 跳转型指由客户端浏览器重新对新地址进行请求

  • 代理型是在WEB服务器内部实现跳转

redirect;302
#临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URL给客户端,由客户端重新发起请求;使用相对路径,或者http://或https://开头,状态码:302

permanent;301      

www.bj.com     www.beijing.com
#重写完成后以永久重定向方式直接返回重写后生成的新URL给客户端,由客户端重新发起请求,状态码:301

break;      

www.bj.com
#重写完成后,停止对当前URL在当前location中后续的其它重写操作,而后直接跳转至重写规则配置块之后的其它配置;结束循环,建议在location中使用
#适用于一个URL一次重写 

立即终止匹配,使用该url进行访问

last;
#重写完成后,停止对当前URI在当前location中后续的其它重写操作,而后对新的URL启动新一轮重写检查,不建议在location中使用
#适用于一个URL多次重写,要注意避免出现超过十次以及URL重写后返回错误的给用户301

停止本location中的匹配,开启新一轮的location匹配

 6.4 防盗链

 防盗链基于客户端携带的referer实现,referer是记录打开一个页面之前记录是从哪个页面跳转过来的标记信息,如果别人只链接了自己网站图片或某个单独的资源,而不是打开了网站的整个页面,这就是盗链,referer就是之前的那个网站域名,正常的referer信息有以下几种:

none:#请求报文首部没有referer首部,比如用户直接在浏览器输入域名访问web网站,就没有referer信息。
blocked:#请求报文有referer首部,但无有效值,比如为空。
server_names:#referer首部中包含本主机名及即nginx 监听的server_name。
arbitrary_string:#自定义指定字符串,但可使用*作通配符。示例: *.kgc.org www.kgc.*
regular expression:#被指定的正则表达式模式匹配到的字符串,要使用~开头,例如:~.*\.kgc\.com

 实现盗链

在二机器上:
systemctl   stop firewalld
setenforce  0
yum install epel-release.noarch -y
yum install nginx
cd /usr/share/nginx/html
vim  index.html
<html>
<body>
<h1>this is yunjisuan  </h1>
<img src="http://www.pc.com/a.jpg"/>
</body>
</html>
systemctl start nginx   

vim   /etc/nginx/nginx.conf
41         server_name  www.zb.com;
修改41行如上

真机上 添加dns  解析
C:\Windows\System32\drivers\etc   
打开  hosts  文件  
第二台机器的IP地址       www.zb.com
真机上测试
www.accp.com  是否可以打开图片

第一胎服务器
vim   /apps/nginx/conf.d/pc.conf
server{
        listen 80;
        server_name  www.pc.com;
        root    /data/nginx/pc;
        location  / {
        root  /data/nginx/pc;
}
        location ~* \.(jpg|gif|swf|jpeg|bmp)$ {
         root  /data/nginx/pc;
         valid_referers none blocked *.pc.com pc.com;
         if ( $invalid_referer ) {
           #rewrite ^/ http://www.pc.com/error.png;
           return   403;
        }
        }
}
}

cd  /data/nginx/pc/
拖入两张图片   a.jpg     error.png
再次测试www.zb.com  是否可以打开图片

七、反向代理

反向代理:reverse proxy,指的是代理外网用户的请求到内部的指定的服务器,并将数据返回给用户的一种方式,这是用的比较多的一种方式。

Nginx 除了可以在企业提供高性能的web服务之外,另外还可以将 nginx 本身不具备的请求通过某种预定义的协议转发至其它服务器处理,不同的协议就是Nginx服务器与其他服务器进行通信的一种规范,主要在不同的场景使用以下模块实现不同的功能。

ngx_http_proxy_module: #将客户端的请求以http协议转发至指定服务器进行处理    七层
ngx_http_upstream_module #用于定义为proxy_pass,fastcgi_pass,uwsgi_pass等指令引用的后端服务器分组    负载均衡
ngx_stream_proxy_module:#将客户端的请求以tcp协议转发至指定服务器处理    四层
ngx_http_fastcgi_module:#将客户端对php的请求以fastcgi协议转发至指定服务器助理
ngx_http_uwsgi_module: #将客户端对Python的请求以uwsgi协议转发至指定服务器处理

7.1 实现 http 反向代理

官方文档: Module ngx_http_proxy_module

7.1.1 http 协议反向代理

7.1.1.1 反向代理配置参数

proxy_pass; 
#用来设置将客户端请求转发给的后端服务器的主机,可以是主机名(将转发至后端服务做为主机头首部)、IP
地址:端口的方式
#也可以代理到预先设置的主机群组,需要模块ngx_http_upstream_module支持

#示例:
10.0.0.8/web
 location /web {
   index index.html;
   proxy_pass http://10.0.0.18:8080;

#8080后面无uri,即无 / 符号,需要将location后面url 附加到proxy_pass指定的url后面,此行为类似于root
#proxy_pass指定的uri不带斜线将访问的/web,等于访问后端服务器
http://10.0.0.18:8080/web/index.html,即后端服务器配置的站点根目录要有web目录才可以被访问
    # http://nginx/web/index.html ==> http://10.0.0.18:8080/web/index.html
    
proxy_pass http://10.0.0.18:8080/;   #8080后面有uri,即有 / 符号,相当于置换,即访问/web时实际返回proxy_pass后面uri内容.此行为类似于alias 
    #proxy_pass指定的uri带斜线,等于访问后端服务器的http://10.0.0.18:8080/index.html 内容返回给客户端
 }  # http://nginx/web/index.html ==> http://10.0.0.18:8080
 
#重启Nginx测试访问效果:
#curl -L http://www.kgc.org/web

#如果location定义其uri时使用了正则表达式模式(包括~,~*,但不包括^~),则proxy_pass之后必须不能使用uri; 即不能有/ ,用户请求时传递的uri将直接附加至后端服务器之后
server {
 ...
 server_name HOSTNAME;
 location ~|~* /uri/ {
 proxy_pass http://host:port; #proxy_pass后面的url 不能加/
 }
 ...
 }
 http://HOSTNAME/uri/ --> http://host/uri/
 
proxy_hide_header field;
#用于nginx作为反向代理的时候,在返回给客户端http响应时,隐藏后端服务器相应头部的信息,可以设置
在http,server或location块
#示例: 隐藏后端服务器ETag首部字段
 location /web {
   index index.html;
   proxy_pass http://10.0.0.18:8080/; 
   proxy_hide_header ETag;
 }
 
proxy_pass_header field;
#默认nginx在响应报文中不传递后端服务器的首部字段Date, Server, X-Pad, X-Accel等参数,如果
要传递的话则要使用 proxy_pass_header field声明将后端服务器返回的值传递给客户端
#field 首部字段大小不敏感
#示例:透传后端服务器的Server和Date首部给客户端,同时不再响应报中显示前端服务器的Server字段
proxy_pass_header Server;
proxy_pass_header Date;


proxy_pass_request_body on | off; 
#是否向后端服务器发送HTTP实体部分,可以设置在http,server或location块,默认即为开启


proxy_pass_request_headers on | off; 
#是否将客户端的请求头部转发给后端服务器,可以设置在http,server或location块,默认即为开启

7.1.1.2 实战案例: 反向代理单台web服务器
7-1   代理服务器 
vim /apps/nginx/conf.d/pc.conf
server{
        listen 80;
        server_name  www.pc.com;
        root    /data/nginx/pc;
     location  / {
        proxy_pass http://192.168.91.101;
}

}


7-2   真实服务器 
yum  install   httpd  -y
cd  /var/www/html
echo   "real  server 101"  > index.html
systemctl   stop nginx
systemctl	start httpd


7-3   客户机
vim  /etc/hosts
192.168.91.100  www.pc.com


代理服务器
server{
        listen 80;
        server_name  www.pc.com;
        root    /data/nginx/pc;
     location  / {
        root  /data/nginx/pc;
        proxy_pass http://192.168.91.101;
}

}

真实服务器
yum install httpd -y
cd /var/www/html/
echo "real server httpd" >index.html

建立大文件查看连接情况
dd if=/dev/zero   of=test.img    count=1  bs=1G


找台服务器访问
curl www.pc.com
wget --limit-rate=1024 www.pc.com/test.img



修改端口号
真实服务器
httpd  服务器修改端口号

server{
        listen 80;
        server_name  www.pc.com;
        root    /data/nginx/pc;
     location  / {
        root  /data/nginx/pc;
        proxy_pass http://192.168.91.101:8080;
}

}

在真实服务器上 做防火墙规则
iptables -A INPUT  -s 192.168.91.100 -j DROP
客户端再次访问  会出现504网关超时(有可能只是处理时间久,服务器不一定挂了),时间较长1分钟,没有定义代理超时时间

iptables -A INPUT  -s 192.168.91.100 -j REJECT
客户端再次访问  会出现502,一般出现502 代表后端真实服务器挂了
7.1.1.3 实战案例:动静分离
server {
 listen 80;
 server_name www.kgc.org;
 location / {
   index index.html index.php;
   root /data/nginx/html/pc;
   }
 location /api {
   #proxy_pass http://10.0.0.18:80/; #注意有后面的/, 表示置换
   proxy_pass http://192.168.91.101;  #后面没有 / , 表示追加
 }
}



server {
......
 location ~* \.(jpe?g|png|bmp|gif)$ {
   proxy_pass http://192.168.91.103;     #如果加/ 语法出错                             
                                         
 }
}

#如果 http://10.0.0.18/ 有 / 语法出错



server{
        listen 80;
        server_name  www.pc.com;
        root    /data/nginx/pc;
     location  / {
        root  /data/nginx/pc;
}
     location  /api {
        root  /data/nginx/pc;
        proxy_pass http://192.168.91.101:8080;

        }
     location ~* \.(jpg|jpeg|png|gif|bmp)$ {
        root  /data/nginx/pc;
        proxy_pass http://192.168.91.102;
        }

}
7.1.1.4反向代理示例:缓存功能

关闭后端服务器后,图片无法访问

缓存功能默认关闭,需要开启

proxy_cache zone_name | off; 默认off
#指明调用的缓存,或关闭缓存机制;Context:http, server, location
#zone_name 表示缓存的名称.需要由proxy_cache_path事先定义

proxy_cache_key string;
#缓存中用于“键”的内容,默认值:proxy_cache_key $scheme$proxy_host$request_uri;



proxy_cache_valid [code ...] time;
#定义对特定响应码的响应内容的缓存时长,定义在http{...}中
 示例:
 proxy_cache_valid 200 302 10m;
 proxy_cache_valid 404 1m;
 
 
 
proxy_cache_path;
#定义可用于proxy功能的缓存;Context:http   必须放在http语句中
proxy_cache_path path [levels=levels] [use_temp_path=on|off] 
keys_zone=zone_name:size [inactive=time] [max_size=size] [manager_files=number] 
[manager_sleep=time] [manager_threshold=time] [loader_files=number] 
[loader_sleep=time] [loader_threshold=time] [purger=on|off] 
[purger_files=number] [purger_sleep=time] [purger_threshold=time];


#示例:在http配置定义缓存信息
   proxy_cache_path /var/cache/nginx/proxy_cache #定义缓存保存路径,proxy_cache会自动创建
   levels=1:2:2 #定义缓存目录结构层次,1:2:2可以生成2^4x2^8x2^8=2^20=1048576个目录
   keys_zone=proxycache:20m #指内存中缓存的大小,主要用于存放key和metadata(如:使用次数),一般1M可存放8000个左右的key
   inactive=120s  #缓存有效时间  
   max_size=10g; #最大磁盘占用空间,磁盘存入文件内容的缓存空间最大值
   
   
#调用缓存功能,需要定义在相应的配置段,如server{...};或者location等
proxy_cache proxycache;
proxy_cache_key $request_uri; #对指定的数据进行MD5的运算做为缓存的key
proxy_cache_valid 200 302 301 10m; #指定的状态码返回的数据缓存多长时间
proxy_cache_valid any 1m;   #除指定的状态码返回的数据以外的缓存多长时间,必须设置,否则不会缓存


proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | off ; #默认是off
#在被代理的后端服务器出现哪种情况下,可直接使用过期的缓存响应客户端

#示例
proxy_cache_use_stale error http_502 http_503;


proxy_cache_methods GET | HEAD | POST ...;
#对哪些客户端请求方法对应的响应进行缓存,GET和HEAD方法总是被缓存

扩展知识:清理缓存

方法1: rm -rf 缓存目录
方法2: 第三方扩展模块ngx_cache_purge 

proxy_cache_path /data/nginx/proyxcache   levels=1:1:1 keys_zone=proxycache:20m inactive=120s max_size=1g;


http  语句
1:1:1  16个二进制     2^16/2^16/2^16       2^48


server {
   listen 80;
   proxy_cache proxycache;
   proxy_cache_key $request_uri;
   #proxy_cache_key $host$uri$is_args$args;
   proxy_cache_valid 200 302 301 10m;
   proxy_cache_valid any 5m;
   server_name www.kgc.com;
   root /data/nginx/pc;
  location / {
  root /data/nginx/pc;
  }
  location /api {
  proxy_pass http://192.168.91.101:9527;
  }
  location ~* \.(jpg|png|gif|html)$ {
  proxy_pass http://192.168.91.102;
  }

}

实现缓存实际操作

在未开启缓存前可以测试下载速度
ab -c100 -n1000 http://www.pc.com/3m.jpg


去代理服务器上 添加操作
先去   主配置文件 的 http模块 中加入下方配置
proxy_cache_path /data/nginx/proyxcache   levels=1:1:1 keys_zone=proxycache:20m inactive=120s max_size=1g;

再去 子配置文件中添加

server{
        listen 80;
        server_name  www.pc.com;
        proxy_cache proxycache;
        proxy_cache_key $request_uri;    www.kg.com/a.jpg
        #proxy_cache_key $host$uri$is_args$args;
        proxy_cache_valid 200 302 301 10m;
        proxy_cache_valid any 5m;
        root    /data/nginx/pc;
     location  / {
        root  /data/nginx/pc;
}
     location  /api {
        root  /data/nginx/pc;
        proxy_pass http://192.168.91.101:8080;

        }
     location ~* \.(jpg|jpeg|png|gif|bmp)$ {
        root  /data/nginx/pc;
        proxy_pass http://192.168.91.102;
        }

}
7.1.1.5 实现反向代理客户端 IP 透传

[root@centos8 ~]# cat /apps/nginx/conf/conf.d/pc.conf
server {
 listen 80;
 server_name www.kgc.org;
 location / {
   index index.html index.php;
   root /data/nginx/html/pc;
   proxy_pass http://10.0.0.18;
    #proxy_set_header X-Real-IP $remote_addr;                   #只添加客户端IP到请求报文头部,转发至后端服务器
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #添加客户端IP和反向代理服务器IP到请求报文头部
 }
}
#重启nginx
[root@centos7 ~]#systemctl restart nginx
#后端Apache配置:
[root@centos7 ~]#vim /etc/httpd/conf/httpd.conf
 LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
#重启apache访问web界面并验证apache日志
 [root@centos8 ~]#cat /var/log/httpd/access_log
10.0.0.1 10.0.0.8 - - [05/Mar/2019:00:40:46 +0800] "GET / HTTP/1.0" 200 19 "-"
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) 
Chrome/72.0.3626.119 Safari/537.36"
#Nginx配置:
[root@centos8 conf.d]# cat /apps/nginx/conf/nginx.conf
"$http_x_forwarded_for"' #默认日志格式就有此配置
#重启nginx访问web界面并验证日志格式:
10.0.0.8 - - [04/Mar/2019:16:40:51 +0800] "GET / HTTP/1.0" 200 24 "-"
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) 
Chrome/72.0.3626.119 Safari/537.36" "10.0.0.1"
7.1.1.6 http反向代理负载均衡

Nginx可以将客户端的请求转发至单台后端服务器但是无法转发至特定的一组的服务器,而且不能对后端服务器提供相应的服务器状态监测,Nginx 可以基于ngx_http_upstream_module模块提供服务器分组转发、权重分配、状态监测、调度算法等高级功能

官方文档: https://nginx.org/en/docs/http/ngx_http_up

#自定义一组服务器,配置在http块内
upstream   web { 
 server 192.168.91.100    调度算法
 server 192.168.91.101
}

location  / {
pass_proxy  http://web/
}


#示例
upstream backend {
   server backend1.example.com weight=5;     权重
   server 127.0.0.1:8080       max_fails=3  fail_timeout=30s;
   server unix:/tmp/backend3;
   server backup1.example.com backup;
}
server address [parameters];
#配置一个后端web服务器,配置在upstream内,至少要有一个server服务器配置。
#server支持的parameters如下:
weight=number #设置权重,默认为1,实现类似于LVS中的WRR,WLC等
max_conns=number  #给当前后端server设置最大活动链接数,默认为0表示没有限制
max_fails=number  #后端服务器的下线条件,当客户端访问时,对本次调度选中的后端服务器连续进行检测多少次,如果都失败就标记为不可用,默认为1次,当客户端访问时,才会利用TCP触发对探测后端服务器健康性检查,而非周期性的探测
fail_timeout=time #后端服务器的上线条件,对已经检测到处于不可用的后端服务器,每隔此时间间隔再次进行检测是否恢复可用,如果发现可用,则将后端服务器参与调度,默认为10秒
backup  #设置为备份服务器,当所有后端服务器不可用时,才会启用此备用服务器 sorry server   自己不能转自己
down    #标记为down状态
resolve #当server定义的是主机名的时候,当A记录发生变化会自动应用新IP而不用重启Nginx

hash KEY [consistent];
#基于指定请求报文中首部字段或者URI等key做hash计算,使consistent参数,将使用ketama一致性

www.kgc.com/test1   

hash  test1      103  


hash算法,适用于后端是Cache服务器(如varnish)时使用,consistent定义使用一致性hash运算,一
致性hash基于取模运算
hash $request_uri consistent; #基于用户请求的uri做hash
hash $cookie_sessionid  #基于cookie中的sessionid这个key进行hash调度,实现会话绑定


ip_hash;
#源地址hash调度方法,基于的客户端的remote_addr(源地址IPv4的前24位或整个IPv6地址)做hash计算,以实现会话保持


least_conn;
#最少连接调度算法,优先将客户端请求调度到当前连接最少的后端服务器,相当于LVS中的WLC


轮询
加权轮询
hash    ip  hash
最少连接数

实际操作

http {
 upstream web {
  server 192.168.91.101:80;
  server 192.168.91.103:80;
}
........
}

[root@localhost nginx]#vim conf.d/test.conf 

server {
     listen 80;
     server_name www.kgc.com;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     root /data/nginx/pc;
     location /  {
     root /data/nginx/pc;
     proxy_pass http://web;           
}

}
7.1.1.7 Nginx tcp负载均衡四层

Nginx在1.9.0版本开始支持tcp模式的负载均衡,在1.9.13版本开始支持udp协议的负载,udp主要用于DNS的域名解析,其配置方式和指令和http 代理类似,其基于ngx_stream_proxy_module模块实现tcp负载,另外基于模块ngx_stream_upstream_module实现后端服务器分组转发、权重分配、状态监测、调度算法等高级功能。如果编译安装,需要指定 --with-stream 选项才能支持ngx_stream_proxy_module模块。

官方文档:

Module ngx_stream_proxy_module

Module ngx_stream_upstream_module

http  同级别的 

stream { #定义stream相关的服务;Context:main

   upstream backend { #定义后端服务器
       hash $remote_addr consistent; #定义调度算法
       server backend1.example.com:12345 weight=5; #定义具体server
       server 127.0.0.1:12345      max_fails=3 fail_timeout=30s;
       server unix:/tmp/backend3;
   }

   upstream dns {  #定义后端服务器
       server 10.0.0.1:53535;  #定义具体server
       server dns.example.com:53;
   }

   server { #定义server
       listen 12345; #监听IP:PORT
       proxy_connect_timeout 1s; #连接超时时间
       proxy_timeout 3s; #转发超时时间
       proxy_pass backend; #转发到具体服务器组
   }

   server {
       listen 127.0.0.1:53 udp reuseport;
       proxy_timeout 20s;
       proxy_pass dns;
   }

   server {
       listen [::1]:12345;
       proxy_pass unix:/tmp/stream.socket;
   }

}

7.1.1.8 Redis负载均衡

 后端服务器

#安装两台redis服务器
[root@centos8 ~]# yum -y install redis 
[root@centos8 ~]# sed -i '/^bind /c bind 0.0.0.0' /etc/redis.conf
[root@centos8 ~]# systemctl enable --now redis
[root@centos8 ~]# ss -tnl | grep 6379
LISTEN     0      128         *:6379                     *:* 

nginx 配置

[root@centos7 ~]# vim /apps/nginx/conf/nginx.conf
include /apps/nginx/conf/tcp/tcp.conf; #注意此处的include与http模块平级
[root@centos7 ~]# mkdir /apps/nginx/conf/tcp
[root@centos7 ~]# cat /apps/nginx/conf/tcp/tcp.conf
stream {
 upstream redis_server {
    #hash $remote_addr consistent;
   server 10.0.0.18:6379 max_fails=3 fail_timeout=30s;
   server 10.0.0.28:6379 max_fails=3 fail_timeout=30s;
 }
 server {
   listen 10.0.0.8:6379;
   proxy_connect_timeout 3s;
   proxy_timeout 3s;
   proxy_pass redis_server;
 }
}
#重启nginx并访问测试
[root@centos7 ~]# systemctl restart nginx
[root@centos7 ~]# ss -tnl | grep 6379
LISTEN     0      128    10.0.0.8:6379                     *:*  
#测试通过nginx 负载连接redis:
[root@centos8 ~]#redis-cli -h 10.0.0.8 set name wang

  • 20
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值