美文网首页
32-高性能WEB服务NGINX(一)

32-高性能WEB服务NGINX(一)

作者: Liang_JC | 来源:发表于2020-05-05 20:26 被阅读0次

    本章内容
    ◆ I/O模型
    ◆ nginx介绍
    ◆ nginx安装
    ◆ nginx各种模块实现web服务
    ◆ nginx实现fastcgi反代代理
    ◆ nginx实现http负载均衡
    ◆ nginx实现tcp反向代理
    ◆ tengine实现
    ◆ nginx高并发Linux内核优化

    性能影响

    • 有很多研究都表明,性能对用户的行为有很大的影响:
      ● 79%的用户表示不太可能再次打开一个缓慢的网站
      ● 47%的用户期望网页能在2秒钟以内加载
      ● 40%的用户表示如果加载时间超过三秒钟,就会放弃这个网站
      ● 页面加载时间延迟一秒可能导致转换损失7%,页面浏览量减少11%
      ● 8秒定律:用户访问一个网站时,如果等待网页打开的时间超过8秒,会有超过30%的用户放弃等待

    影响用户体验的几个因素

    ● 客户端硬件配置
    ● 客户端网络速率
    ● 客户端与服务端距离
    ● 服务端网络速率
    ● 服务端硬件配置
    ● 服务端架构设计
    ● 服务端应用程序工作模式
    ● 服务端并发数量
    ● 服务端响应文件大小及数量
    ● 服务端I/O压力

    Httpd MPM

    • prefork:进程模型,两级结构,主进程master负责生成子进程,每个子进程负责响应一个请求
    • worker:线程模型,三级结构,主进程master负责生成子进程,每个子进程负责生成多个线程,每个线程响应一个请求
    • event:线程模型,三级结构,主进程master负责生成子进程,每个子进程响应多个请求

    I/O介绍

    • I/O:
      网络IO:本质是socket文件读取
      磁盘IO:
    • 每次IO,都要经由两个阶段:
      第一步:将数据从文件先加载至内核内存空间(缓冲区),等待数据准备完成,时间较长
      第二步:将数据从内核缓冲区复制到用户空间的进程的内存中,时间较短

    I/O模型

    • 同步/异步:关注的是消息通信机制
      同步:synchronous,调用者等待被调用者返回消息,才能继续执行
      异步:asynchronous,被调用者通过状态、通知或回调机制主动通知调用者被调用者的运行状态
    • 阻塞/非阻塞:关注调用者在等待结果返回之前所处的状态
      阻塞:blocking,指IO操作需要彻底完成后才返回到用户空间,调用结果返回之前,调用者被挂起
      非阻塞:nonblocking,指IO操作被调用后立即返回给用户一个状态值,无需等到IO操作彻底完成,最终的调用结果返回之前,调用者不会被挂起
    • I/O模型:
      阻塞型、非阻塞型、复用型、信号驱动型、异步

    阻塞IO模型

    image.png
    • 阻塞IO模型是最简单的IO模型,用户线程在内核进行IO操作时被阻塞

    • 用户线程通过系统调用read发起IO读操作,由用户空间转到内核空间。内核等到数据包到达后,然后将接收的数据拷贝到用户空间,完成read操作

    • 用户需要等待read将数据读取到buffer后,才继续处理接收的数据。整个IO请求的过程中,用户线程是被阻塞的,这导致用户在发起IO请求时,不能做任何事情,对CPU的资源利用率不够

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

    • 缺点:每个连接需要独立的进程/线程单独处理,当并发请求量大时为了维护程序,内存、线程切换开销较大,这种模型在实际生产中很少使用

    • 对于单线程的网络服务,这样做就会有卡死的问题。因为当等待时,整个线程会被挂起,无法执行,也无法做其他的工作。这种Block是不会影响同时运行的其他程序(进程)的,因为现代操作系统都是多任务的,任务之间的切换是抢占式的。这里Block只是指Block当前的进程

    • 网络服务为了同时响应多个并发的网络请求,必须实现为多线程,每个线程处理一个网络请求。线程数随着并发连接数线性增长。 2000年之前很多网络服务器就是这么实现的。 但有两个问题:线程越多,Context Switch就越多,而Context Switch是一个比较重的操作,会无谓浪费大量的CPU。每个线程同时也会占用一定的内存作为线程的栈

    • 虽可通过线程池技术既能并发的处理请求,又不会产生大量线程。但这样会限制最大并发的连接数。

    • 当调用read接受网络请求时,有数据到了就处理,没数据到时,实际上是可以干别的。之所以使用大量线程,仅仅是因为Block发生

      总结:

      应用程序接收到用户一个请求,应用程序发起系统调用内核完成工作,内核从网络或者硬盘上得到数据,发往应用程序的用户空间中,此时应用程序一直处于等待状态,不能做任何事

    同步非阻塞IO模型

    image.png
    • 用户线程发起IO请求时立即返回。但并未读取到任何数据,用户线程需要不断地发起IO请求,直到数据到达后,才真正读取到数据,继续执行。即 “轮询”机制

    • 存在两个问题:如果有大量文件描述符都要等,那么就得一个一个的read。这会带来大量的Context Switch(read是系统调用,每调用一次就得在用户态和核心态切换一次)。轮询的时间不好把握。这里是要猜多久之后数据才能到。等待时间设的太长,程序响应延迟就过大;设的太短,就会造成过于频繁的重试,干耗CPU而已

    • 是比较浪费CPU的方式,一般很少直接使用这种模型,而是在其他IO模型中使用非阻塞IO这一特性

      总结:
      应用程序接收到用户一个请求,应用程序发起系统调用内核完成工作,应用程序发起调用后处于空闲状态,不用等待系统回应,所以应用程序会不断询问系统处理结果。当系统处理完毕后就会回应并发往应用程序的用户空间

    I/O多路复用模型

    image.png
    • IO多路复用(IO Multiplexing) :是一种机制,程序注册一组socket文件描述符给操作系统,表示“我要监视这些fd是否有IO事件发生,有了就告诉程序处理”

    • IO多路复用是要和NIO一起使用的。 NIO和IO多路复用是相对独立的。 NIO仅仅是指IO API总是能立刻返回,不会被Blocking;而IO多路复用仅仅是操作系统提供的一种便利的通知机制。操作系统并不会强制这俩必须得一起用,可以只用IO多路复用 + BIO,这时还是当前线程被卡住。 IO多路复用和NIO是要配合一起使用才有实际意义

    • IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,就通知该进程

    • 多个连接共用一个等待机制,本模型会阻塞进程,但是进程是阻塞在select或者poll这两个系统调用上,而不是阻塞在真正的IO操作上

    • 用户首先将需要进行IO操作添加到select中,同时等待select系统调用返回。当数据到达时,IO被激活,select函数返回。用户线程正式发起read请求,读取数据并继续执行

    • 从流程上来看,使用select函数进行IO请求和同步阻塞模型没有太大的区别,甚至还多了添加监视IO,以及调用select函数的额外操作,效率更差。并且阻塞了两次,但是第一次阻塞在select上时,select可以监控多个IO上是否已有IO操作准备就绪,即可达到在同一个线程内同时处理多个IO请求的目的。而不像阻塞IO那种,一次只能监控一个IO

    • 虽然上述方式允许单线程内处理多个IO请求,但是每个IO请求的过程还是阻塞的(在select函数上阻塞),平均时间甚至比同步阻塞IO模型还要长。如果用户线程只是注册自己需要的IO请求,然后去做自己的事情,等到数据到来时再进行处理,则可以提高CPU的利用率

    • IO多路复用是最常使用的IO模型,但是其异步程度还不够“彻底”,因它使用了会阻塞线程的select系统调用。因此IO多路复用只能称为异步阻塞IO模型,而非真正的异步IO

      总结:

      多个app发起请求,select进程接受请求,select进程发往内核处理,如果内核已把数据准备好了,发信息给app(在此之前app处于阻塞状态),此时app参与了复制过程,内核把数据复制到用户空间并返回了成功结果,app就可以进行通讯了

    信号驱动IO模型

    image.png
    • 信号驱动IO:signal-driven I/O

    • 用户进程可以通过sigaction系统调用注册一个信号处理程序,然后主程序可以继续向下执行,当有IO操作准备就绪时,由内核通知触发一个SIGIO信号处理程序执行,然后将用户进程所需要的数据从内核空间拷贝到用户空间

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

    • 对于 TCP 而言,信号驱动的 I/O 方式近乎无用,因为导致这种通知的条件为数众多,每一个来进行判别会消耗很大资源,与前几种方式相比优势尽失

    • 优点:线程并没有在等待数据时被阻塞,可以提高资源的利用率

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

      总结:

      app进程发起系统调用后,有异步行为,内核准备数据发到内核发送数据到用户空间期间不阻塞(app可以做其他事)

    异步IO模型

    image.png
    • 异步IO与信号驱动IO最主要的区别是信号驱动IO是由内核通知应用程序何时可以进行IO操作,而异步IO则是由内核告诉用户线程IO操作何时完成。信号驱动IO当内核通知触发信号处理程序时,信号处理程序还需要阻塞在从内核空间缓冲区拷贝数据到用户空间缓冲区这个阶段,而异步IO直接是在第二个阶段完成后,内核直接通知用户线程可以进行后续操作了

    • 由 POSIX 规范定义,应用程序告知内核启动某个操作,并让内核在整个操作(包括将数据从内核拷贝到应用程序的缓冲区)完成后通知应用程序

    • 优点:异步 I/O 能够充分利用 DMA 特性,让 I/O 操作与计算重叠

    • 缺点:要实现真正的异步 I/O,操作系统需要做大量的工作。目前 Windows 下通过 IOCP 实现了真正的异步 I/O,在 Linux 系统下,Linux 2.6才引入,目前AIO 并不完善,因此在 Linux 下实现高并发网络编程时以 IO 复用模型模式+多线程任务的架构基本可以满足需求

      总结:

      app进程发起系统调用后,由内核完成,内核在处理过程中app全都不阻塞

    I/O模型的具体实现

    • 这五种 I/O 模型中,越往后,阻塞越少,理论上效率也是最优前四种属于同步I/O,因为其中真正的 I/O 操作(recvfrom)将阻塞进程/线程,只有异步 I/O 模型才与 POSIX 定义的异步 I/O 相匹配
    • 主要实现方式有以下几种:
      Select:Linux实现对应,I/O复用模型,BSD4.2最早实现,POSIX标准,一般操作系统均有实现
      Poll:Linux实现,对应I/O复用模型,System V unix最早实现
      Epoll:Linux特有,对应I/O复用模型,具有信号驱动I/O模型的某些特性
      Kqueue:FreeBSD实现,对应I/O复用模型,具有信号驱动I/O模型某些特性
      /dev/poll:SUN的Solaris实现,对应I/O复用模型,具有信号驱动I/O模型的某些特性
      Iocp Windows实现,对应第5种(异步I/O)模型

    select/poll/epoll

    image.png image.png
    • Select:POSIX所规定,目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点,本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理
    • 缺点
      ● 单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,可以通过修改宏定义FD_SETSIZE,再重新编译内核实现,但是这样也会造成效率的降低
      ● 单个进程可监视的fd数量被限制,默认是1024,修改此值需要重新编译内核
      ● 对socket是线性扫描,即采用轮询的方法,效率较低
      ● select 采取了内存拷贝方法来实现内核将 FD 消息通知给用户空间,这样一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大
    #查看源码内核FD_SETSIZE的值
    find linux-5.1.4/ -type f | xargs grep "FD_SETSIZE"
    
    • poll
      ● 本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态
      ● 其没有最大连接数的限制,原因是它是基于链表来存储的
      ● 大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义
      ● poll特点是“水平触发”,如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd
      ● 边缘触发:只通知一次

    • epoll:在Linux 2.6内核中提出的select和poll的增强版本
      ● 支持水平触发LT和边缘触发ET,最大的特点在于边缘触发,它只告诉进程哪些fd刚刚变为就需态,并且只会通知一次
      ● 使用“事件”的就绪通知方式,通过epoll_ctl注册fd,一旦该fd就绪,内核就会采用类似callback的回调机制来激活该fd,epoll_wait便可以收到通知

    • 优点:
      ● 没有最大并发连接的限制:能打开的FD的上限远大于1024(1G的内存能监听约10万个端口),具体查看/proc/sys/fs/file-max,此值和系统内存大小相关
      ● 效率提升:非轮询的方式,不会随着FD数目的增加而效率下降;只有活跃可用的FD才会调用callback函数,即epoll最大的优点就在于它只管理“活跃”的连接,而跟连接总数无关
      ● 内存拷贝,利用mmap(Memory Mapping)加速与内核空间的消息传递;即epoll使用mmap减少复制开销

    零拷贝

    • 传统Linux中 I/O 的问题
    • 传统的 Linux 系统的标准 I/O 接口(read、 write)是基于数据拷贝的,也就是 数据都是 copy_to_user 或者 copy_from_user,这样做的好处是,通过中间缓存的机制,减少磁盘 I/O 的操作,但是坏处也很明显,大量数据的拷贝,用户态和内核态的频繁切换,会消耗大量的 CPU 资源,严重影响数据传输的性能, 统计表明,在Linux协议栈中,数据包在内核态和用户态之间的拷贝所用的时间,甚至占到了数据包整个处理流程时间的57.1%
    • 什么是零拷贝
    • 零拷贝就是上述问题的一个解决方案,通过尽量避免拷贝操作来缓解 CPU 的压 力。零拷贝并没有真正做到“0” 拷贝,它更多是一种思想,很多的零拷贝技术 都是基于这个思想去做的优化

    nginx介绍

    • nginx: engine X,是由1994年毕业于俄罗斯国立莫斯科鲍曼科技大学的同学为俄罗斯rambler.ru公司开发的,开发工作最早从2002年开始,第一次公开发布时间是2004年10月4日,版本号是0.1.0

    • nginx有商业版和社区版,2019年3月11日F5 Networks 6.7亿美元的价格收购

    • nginx 是免费,开源,高性能的HTTP和反向代理服务器,邮件代理服务器,通用TCP/UDP代理服务器

    • 解决C10K问题(10K Connections)

    • 官网:http://nginx.org

    • nginx的其它的二次发行版:
      Tengine:由淘宝网发起的Web服务器项目。它在Nginx的基础上,针对大访问量网站的需求,添加了很多高级功能和特性。 Tengine的性能和稳定性已经在大型的网站如淘宝网,天猫商城等得到了很好的检验。从2011年12月开始,Tengine成为一个开源项目,官网 http://tengine.taobao.org/
      OpenResty:基于 Nginx 与 Lua 语言的高性能 Web 平台, 章亦春
      官网:http://openresty.org/cn/

    • 特性:
      模块化设计,较好的扩展性
      高可靠性
      支持热部署:不停机更新配置文件,升级版本,更换日志文件
      低内存消耗:10000个keep-alive连接模式下的非活动连接,仅需2.5M内存
      event-driven,aio,mmap,sendfile

    • 基本功能:
      静态资源的web服务器
      http协议反向代理服务器
      pop3/imap4协议反向代理服务器
      FastCGI(LNMP),uWSGI(python)等协议
      模块化(非DSO),如zip,SSL模块

    nginx的程序架构

    • web服务相关的功能:
      虚拟主机(server)
      支持 keep-alive 和管道连接( 共享TCP连接发起并发的HTTP请求)
      访问日志(支持基于日志缓冲提高其性能)
      url rewrite
      路径别名
      基于IP及用户的访问控制
      支持速率限制及并发数限制
      重新配置和在线升级而无须中断客户的工作进程
      Memcached 的 GET 接口

    • nginx的程序架构:
      master/worker结构
      ● 一个master进程:
      负载加载和分析配置文件、管理worker进程、平滑升级
      ● 一个或多个worker进程
      处理并响应用户请求
      ● 缓存相关的进程:
      cache loader:载入缓存对象
      cache manager:管理缓存对象

    nginx模块

    • nginx高度模块化,但其模块早期不支持DSO机制;1.9.11版本支持动态装载和卸载
    • 模块分类:
      核心模块:core module
      标准模块:
      ● HTTP 模块: ngx_http_*
      HTTP Core modules 默认功能
      HTTP Optional modules 需编译时指定
      ● Mail 模块 ngx_mail_*
      ● Stream 模块 ngx_stream_*
      第三方模块
    • 核心模块:是 Nginx 服务器正常运行 必不可少 的模块,提供 错误日志记录 、配置文件解析 、 事件驱动机制 、 进程管理 等核心功能
    • 标准HTTP模块:提供 HTTP 协议解析相关的功能,比如: 端口配置 、 网页编码设置 、 HTTP响应头设置 等等
    • 可选HTTP模块:主要用于扩展标准的 HTTP 功能,让 Nginx 能处理一些特殊的服务,比如: Flash 多媒体传输 、解析 GeoIP 请求、 网络传输压缩 、 安全协议 SSL 支持等
    • 邮件服务模块:主要用于支持 Nginx 的 邮件服务 ,包括对 POP3 协议、IMAP 协议和 SMTP协议的支持
    • 第三方模块:是为了扩展 Nginx 服务器应用,完成开发者自定义功能,比如:Json 支持、 Lua 支持等

    nginx的功用

    • 静态的web资源服务器
      html,图片,js,css,txt等静态资源
    • 结合FastCGI/uWSGI/SCGI等协议反向代理动态资源请求
    • http/https协议的反向代理
    • imap4/pop3协议的反向代理
    • tcp/udp协议的请求转发(反向代理)

    nginx的安装

    • 官方yum源:
      http://nginx.org/packages/centos/7/x86_64/

    • Fedora-EPEL源:
      https://mirrors.aliyun.com/epel/7/x86_64/

    • 编译安装:

      yum install gcc pcre-devel openssl-devel zlib-devel
      useradd -r -s /sbin/nologin nginx
      ./configure --prefix=/apps/nginx --conf-path=/etc/nginx/nginx.conf --errorlog-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 --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --withhttp_dav_module --with-http_stub_status_module --with-threads --with-file-aio
      make && make install
      
    vim /etc/yum.repos.d/nginx.repo
    [nginx-stable]
    name=nginx stable repo
    baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
    gpgcheck=1
    enabled=1
    gpgkey=https://nginx.org/keys/nginx_signing.key
    module_hotfixes=true
    yum install nginx
    

    编译安装示例

    useradd -r -s /sbin/nologin nginx
    ./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  
    

    小笔记:nginx

    yum install nginx
    systemctl start nginx
    echo "welcome" > /usr/share/nginx/html/index.html
    
    nginx       #启动服务
    nginx -s reload|stop|restart
    nginx -t    #检查配置文件
    nginx -T    #查看配置文件内容
    nginx -V    #查看编译的参数
    

    小笔记:源码编译nginx

    wget http://nginx.org/download/nginx-1.16.1.tar.gz
    tar xf nginx-1.16.1.tar.gz
    yum install gcc pcre-devel openssl-devel zlib-devel
    useradd -r -s /sbin/nologin nginx
    cd nginx-1.16.1
    ./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
    ln -s /apps/nginx/sbin/nginx /usr/sbin/
    
    /apps/nginx/html    #主页文件目录
    

    nginx目录结构和命令

    • ls /apps/nginx/
      html是测试页,sbin是主程序
    • ls /apps/nginx/sbin/
      nginx 只有一个程序文件
    • ls /apps/nginx/html/
      50x.html index.html 测试网页
    • nginx:默认为启动nginx
      -h 查看帮助选项
      -V 查看版本和配置选项
      -t 测试nginx语法错误
      -c filename 指定配置文件(default: /etc/nginx/nginx.conf)
      -s signal 发送信号给master进程,signal:stop, quit, reopen, reload
      ● 示例: nginx -s stop 停止nginx
      nginx -s reload 加载配置文件
      -g directives 在命令行中指明全局指令

    nginx配置

    • 配置文件的组成部分:
      ● 主配置文件:nginx.conf
      子配置文件 include conf.d/*.conf
      ● fastcgi, uwsgi,scgi等协议相关的配置文件
      ● mime.types:支持的mime类型
    • 主配置文件的配置指令:
      directive value [value2 ...];
    • 注意:
      (1) 指令必须以分号结尾
      (2) 支持使用配置变量
      内建变量:由Nginx模块引入,可直接引用
      自定义变量:由用户使用set命令定义
      set variable_name value;
      引用变量:$variable_name

    nginx配置文件

    主配置文件结构:四部

    main block:主配置段,即全局配置段,对http,mail都有效
        event {
            ...
        } 事件驱动相关的配置
    http {
        ...
    }   http/https 协议相关配置段
    mail {
        ...
    }   mail 协议相关配置段
    stream {
        ...
    }   stream 服务器相关配置段
    

    http协议相关的配置结构

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

    nginx配置

    • Main 全局配置段常见的配置指令分类
      正常运行必备的配置
      优化性能相关的配置
      用于调试及定位问题相关的配置
      事件驱动相关的配置

    • 帮助文档
      http://nginx.org/en/docs/
      http://tengine.taobao.org/nginx_docs/cn/docs/

    • 正常运行必备的配置:
      ● user
      指定worker进程的运行身份,如组不指定,默认和用户名同名
      Syntax: user user [group];
      Default: user nobody nobody;
      Context: main
      ● pid /PATH/TO/PID_FILE;
      指定存储nginx主进程PID的文件路径
      ● include file | mask;
      指明包含进来的其它配置文件片断
      ● load_module file ;
      模块加载配置文件: /usr/share/nginx/modules/*.conf
      指明要装载的动态模块路径:/usr/lib64/nginx/modules

    • 性能优化相关的配置:
      ● worker_processes number | auto;
      worker进程的数量;通常应该为当前主机的cpu的物理核心数
      ● worker_cpu_affinity cpumask ...;
      worker_cpu_affinity auto [cpumask] 提高缓存命中率
      CPU MASK: 00000001:0号CPU
      00000010:1号CPU
      10000000:7号CPU
      worker_cpu_affinity 0001 0010 0100 1000;
      worker_cpu_affinity 0101 1010;
      ● worker_priority number;
      指定worker进程的nice值,设定worker进程优先级:[-20,20]
      ● worker_rlimit_nofile number;
      所有worker进程能打开的文件数量上限,最好与ulimit -n 的值保持一致,如65535

    • 事件驱动相关的配置:
      events {
      ...
      }
      ● worker_connections #;
      每个worker进程所能够打开的最大并发连接数,如10240
      总最大并发数:worker_processes * worker_connections
      ● use method;
      指明并发连接请求的处理方法,默认自动选择最优方法
      示例:use epoll;

    • 事件驱动相关的配置:
      ● accept_mutex on | off;
      处理新的连接请求的方法;on指由各个worker轮流处理新请求,Off指每个新请求的到达都会通知(唤醒)所有的worker进程,但只有一个进程可获得连接,造成“惊群”,影响性能,默认值为off,可优化为on
      ● multi_accept on|off;
      此指令默认为off,即默认为一个worker进程只能一次接受一个新的网络连 接, on表示每个woker进程可以同时接受所有新的网络连接

    • 调试和定位问题:
      1、 daemon on|off;
      是否以守护进程方式运行,默认是on,即守护进程方式,off 用于调试或docker环境
      2、 master_process on|off;
      是否以master/worker模型运行nginx,默认为on,当指定off 将不启动worker
      3、 error_log file [level] ;
      错误日志文件及其级别;出于调试需要,可设定为debug;但debug仅在编译时使用了“--with-debug” 选项时才有效
      /path/logfile: 记录到文件中
      stderr: 发送到标准错误
      syslog:server-address[,parameter=values] 发送到syslog
      memory:size 内存
      level:debug|info|notice|warn|error|crit|alter|emerg 日志级别

    • http协议的相关配置:

      http {
        ... ...
        server {
            ...
            server_name
            root
            location [OPERATOR] /uri/ {
            ...
            }
        }
        server {
            ...
        }
      }  
      

    ngx_http_core_module

    • 在响应报文中将指定的文件扩展名映射至MIME对应的类型

      include /etc/nginx/mime.types;
      default_type application/octet-stream; #除上面指定的类型外,就为默认的MIME类型,浏览器一般会提示下载
      types {
        text/html html;
        image/gif gif;
        image/jpeg jpg;
      }
      
    • MIME参考文档:
      https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_Types

    • tcp_nodelay on | off;
      在keepalived模式下的连接是否启用TCP_NODELAY选项,即Nagle算法
      当为off时,延迟发送,每发送一个包就需要确认ACK,才发送下一个包
      默认On时,不延迟发送,多个包才确认一次
      可用于:http, server, location

    • tcp_nopush on | off ;
      在开启sendfile,on时合并响应头和数据体在一个包中一起发送

    • sendfile on | off;
      是否启用sendfile功能,在内核中封装报文直接发送,默认Off

    • charset charset | off;
      是否在响应报文中的Content-Type显示指定的字符集,默认off不显示

    • server_tokens on | off | build | string;
      是否在响应报文的Server首部显示nginx版本

    • 如果想自定义响应报文的nginx版本信息,需要修改源码文件,重新编译

    • 如果server_tokens on,修改 src/core/nginx.h 修改第13-14行,如下示例

      define NGINX_VERSION "1.68.9"

      define NGINX_VER "wanginx/" NGINX_VERSION

    • 如果server_tokens off,修改 src/http/ngx_http_header_filter_module.c
      第49行,如下示例:
      static char ngx_http_server_string[] = "Server: nginx" CRLF;
      把其中的nginx改为自己想要的文字即可,如:wanginx

    • ngx_http_core_module
      与套接字相关的配置:

      server { ... }    #配置一个虚拟主机
        server {
            listen address[:PORT]|PORT;
            server_name SERVER_NAME;
            root /PATH/TO/DOCUMENT_ROOT;
        }  
      
    • listen PORT|address[:port]|unix:/PATH/TO/SOCKET_FILE
      listen address[:port] [default_server] [ssl] [http2 | spdy] [backlog=number] [rcvbuf=size] [sndbuf=size];
      default_server 设定为默认虚拟主机,无法匹配虚拟主机时使用
      ssl 限制仅能够通过ssl连接提供服务
      backlog=number 超过并发连接数后,新请求进入后援队列的长度
      rcvbuf=size 接收缓冲区大小
      sndbuf=size 发送缓冲区大小
      注意:
      (1) 基于port;
      listen PORT; 指令监听在不同的端口
      (2) 基于ip的虚拟主机
      listen IP:PORT; IP 地址不同
      (3) 基于hostname
      server_name fqdn; 指令指向不同的主机名

    • server_name name ...;
      ● 虚拟主机的主机名称后可跟多个由空白字符分隔的字符串
      ● 支持*通配任意长度的任意字符
      server_name .magedu.com www.magedu.
      ● 支持~起始的字符做正则表达式模式匹配,性能原因慎用
      server_name ~^www\d+.magedu.com说明: \d 表示 [0-9] ● 匹配优先级机制从高到低 (1) 首先是字符串精确匹配 如:www.magedu.com (2) 左侧*通配符 如:*.magedu.com (3) 右侧*通配符 如:www.magedu.* (4) 正则表达式 如: ~^.*\.magedu\.com
      (5) default_server

    • 定义路径相关的配置
      root
      设置web资源的路径映射;用于指明请求的URL所对应的文档的目录路径,可用于http, server, location, if in location

    server {
        ...
        root /data/www/vhost1;
    }
    示例
        http://www.magedu.com/images/logo.jpg
                --> /data/www/vhosts/images/logo.jpg
    
    • location [ = | ~ | ~* | ^~ ] uri { ... }
      location @name { ... }
      在一个server中location配置段可存在多个,用于实现从uri到文件系统的路径映射;ngnix会根据用户请求的URI来检查定义的所有location,并找出一个最佳匹配,而后应用其配置
      示例:
    server {...
        server_name www.magedu.com;
        location /images/ {
            root /data/imgs/;
        }
    }
        http://www.magedu.com/images/logo.jpg
                --> /data/imgs/images/logo.jpg  
    
    • = 对URI做精确匹配;
    location = / {
         ...
     }
     http://www.magedu.com/ 匹配
    http://www.magedu.com/index.html 不匹配
    
    ^~ 对URI的最左边部分做匹配检查,不区分字符大小写
    ~ 对URI做正则表达式模式匹配,区分字符大小写
    ~* 对URI做正则表达式模式匹配,不区分字符大小写
    不带符号 匹配起始于此uri的所有的uri
    \ 转义符,可将 . * ?等转义为普通符号

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

    • 示例:
    root /vhosts/www/htdocs/;
        http://www.magedu.com/index.html
            --> /vhosts/www/htdocs/index.html
    server {
        root /vhosts/www/htdocs/ ;
        location /admin/ {
            root /webapps/app1/data/;
        }
    }
        http://www.magedu.com/admin/index.html
            --> /webapps/app1/data/admin/index.html
    
    • location示例
    location = / {                      http://www.magedu.com/
    [ configuration A ]
    }
    location / {                        http://www.magedu.com/index.html
    [ configuration B ]
    }
    location /documents/ {              http://www.magedu.com/documents/logo.jpg
    [ configuration C ]
    }
    location ^~ /images/ {              http://www.magedu.com/documents/linux.txt
    [ configuration D ]
    }
    location ~* \.(gif|jpg|jpeg)$ {     http://www.magedu.com/images/logo.jpeg
    [ configuration E ]
    }
    
    • root 指定虚拟主机根目录,在定义location时,文件的绝对路径等于 root+location,
      示例:
    server {
        listen 80;
        server_name www.magedu.net;
        location / {
            root /data/nginx/html/pc;
        }
        location /about {
            root /opt/nginx/html/pc;
            #必须要在html目录中创建一个about目录才可以访问,否则报错
            index index.html;
        }
    }
    #mkdir /opt/nginx/html/pc/about
    #echo about > /opt/nginx/html/pc/about/index.html  
    
    • 生产案例:静态资源配置
    location ^~ /static/ {
        root /data/nginx/static;
    }
    # 或者
    location ~* \.(gif|jpg|jpeg|png|bmp|tiff|tif|css|js|ico)$ {
        root /data/nginx/static;
    }  
    
    • alias path;
      路径别名,文档映射的另一种机制;仅能用于location上下文

      示例:

      http://www.magedu.com/bbs/index.html
      location /bbs {       #注意: /bbs 后建议不要加 /
        alias /web/forum/;  #--> /web/forum/index.html
      }     
      location /bbs/ {
        root /web/forum/;   #--> /web/forum/bbs/index.html
      }     
      #注意:location中使用root指令和alias指令的意义不同
      (a) root,给定的路径对应于location中的/uri 左侧的/
      (b) alias,给定的路径对应于location中的/uri 的完整路径  
      
    • alias定义路径别名,会把访问的路径重新定义到其指定的路径,如下示例:

    server {
        listen 80;
        server_name www.magedu.net;
        location / {
            root /data/nginx/html/pc;
        } 
        #使用alias的时候uri后面如果加了斜杠则下面的路径配置必须加斜杠,否则403
        location /about {   #当访问about时,访问alias定义的/opt/nginx/html/pc内容
        alias /opt/nginx/html/pc;
            index index.html;
        }
    }
    
    • index file ...;
      指定默认网页文件,此指令由ngx_http_index_module模块提供

    • error_page code ... [=[response]] uri;
      定义错误页,以指定的响应状态码进行响应
      可用位置:http, server, location, if in location
      示例:

      error_page 404 /404.html;
      location = /40x.html {
      }
      error_page 404 =200 /404.html
      error_page 500 502 503 504 /50x.html;
      location = /50x.html {
      }  
      
    #生产案例:
    
    listen 80;
    server_name www.magedu.net;
    error_page 500 502 503 504 404 /error.html;
    location = /error.html {
        root /data/nginx/html;
    }  
    
    • try_files file ... uri;
      try_files file ... =code;
      按顺序检查文件是否存在,返回第一个找到的文件或文件夹(结尾加斜线表示为
      文件夹),如果所有文件或文件夹都找不到,会进行一个内部重定向到最后一个
      参数。只有最后一个参数可以引起一个内部重定向,之前的参数只设置内部URI的
      指向

      location /images/ {
        try_files $uri /images/default.jpg;
      }     #说明:/images/default.jpg 为 URI
      location / {
        try_files $uri $uri/index.html $uri.html =404;
      }  
      
    • 定义客户端请求的相关配置

    • keepalive_timeout timeout [header_timeout];
      设定保持连接超时时长,0表示禁止长连接,默认为75s
      示例:在响应头显示此首部字段
      keepalive_timeout 60 60;

    • keepalive_requests number;
      在一次长连接上所允许请求的资源的最大数量,默认为100

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

    • send_timeout time;
      向客户端发送响应报文的超时时长,此处是指两次写操作之间的间隔时长,而非整个响应过程的传输时长

    • client_max_body_size size;
      指定请求报文中实体的最大值,设为0,则不限制,默认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、 3级作为文件名
      client_body_temp_path /var/tmp/client_body 1 2 2
      1 1级目录占1位16进制,即2^4=16个目录 0-f
      2 2级目录占2位16进制,即2^8=256个目录 00-ff
      2 3级目录占2位16进制,即2^8=256个目录 00-ff

    • 上传服务器配置生产案例:

      location /upload {
        client_max_body_size 100m;
        client_body_buffer_size 2048k;
        client_body_temp_path /apps/nginx/temp 1 2 2;
        …
      }  
      
    • 对客户端进行限制的相关配置

    • limit_rate rate;
      限制响应给客户端的传输速率,单位是bytes/second
      默认值0表示无限制

    • 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.1.0/24;
        deny all;
    }
    

    除了GET和HEAD 之外其它方法仅允许192.168.1.0/24网段主机使用

    • 文件操作优化的配置

    • aio on | off | threads[=pool];
      是否启用aio功能,默认off

    • directio size | off;
      当文件大于等于给定大小时,同步(直接)写磁盘,而非写缓存,默认off
      示例:

      location /video/ {
        sendfile on;
        aio on;
        directio 8m;
      }  
      
    • open_file_cache off;
      open_file_cache max=N [inactive=time];
      nginx可以缓存以下三种信息:
      (1) 文件元数据:文件的描述符、文件大小和最近一次的修改时间
      (2) 打开的目录结构
      (3) 没有找到的或者没有权限访问的文件的相关信息
      max=N:可缓存的缓存项上限;达到上限后会使用LRU算法实现管理
      inactive=time:缓存项的非活动时长,在此处指定的时长内未被命中的或
      命中的次数少于open_file_cache_min_uses指令所指定的次数的缓存项即为非活动项,将被删除

    • open_file_cache_errors on | off;
      是否缓存查找时发生错误的文件一类的信息,默认值为off

    • open_file_cache_min_uses number;
      open_file_cache指令的inactive参数指定的时长内,至少被命中此处指定的次数方可被归类为活动项,默认值为1

    • open_file_cache_valid time;
      缓存项有效性的检查频率,默认值为60s

    小笔记:nginx配置文件

    cd /etc/nginx/
    grep -Ev "^#|^$" nginx.conf
    mkdir conf.d/test
    
    vim nginx.conf
    user nginx;                         #指定用户名
    worker_processes 4;                 #进程数,跟CPU核心有关
    #worker_cpu_affinity 00000001 00000010 00000100 00001000 ;      #进程跟CPU绑定
    #worker_priority -20                #优先级-20到20,越小越大
    #worker_rlimit_nofile 65535         #与ulimit -n的值保持一致,配置文件/etc/security/limits.conf
    error_log /var/log/nginx/error.log;
    pid /run/nginx.pid;
    include /usr/share/nginx/modules/*.conf;
    
    events {
        worker_connections 1024;        #每个worker进程所能够打开的最大并发连接数
        #master_process on|off;         #默认为on,当指定off 将不启动worker
    }
    
    http {
        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  /var/log/nginx/access.log  main;
        sendfile            on;         #开启后nopush才有效
        tcp_nopush          on;         #性能优化
        tcp_nodelay         on;         #性能优化
        keepalive_timeout   65;         #保持连接超时时长
        types_hash_max_size 2048;
        include             /etc/nginx/mime.types;
        default_type        application/octet-stream;
        # Load modular configuration files from the /etc/nginx/conf.d directory.
        # See http://nginx.org/en/docs/ngx_core_module.html#include
        # for more information.
        include /etc/nginx/conf.d/*.conf;
        server {
            listen       80 default_server;
            listen       [::]:80 default_server;
            server_name  _;
            root         /usr/share/nginx/html;
            # Load configuration files for the default server block.
            include /etc/nginx/default.d/*.conf;
            location / {
            }
            error_page 404 /404.html;
                location = /40x.html {
            }
            error_page 500 502 503 504 /50x.html;
                location = /50x.html {
            }
        }
    }
    
    vim conf.d/test.conf
    charset utf-8
    server_tokens nginx
    

    小笔记:配置虚拟主机

    #server
    mkdir /data/site1
    mkdir /data/site2
    echo /data/site1/index.html > /data/site1/index.html
    echo /data/site2/index.html > /data/site2/index.html
    
    vim /etc/nginx/conf.d/test.conf
    server_tokens off;
    server {
        server_name www.magedu.net;
        root /data/site1/;
    }
    server {
        server_name www.magedu.tech;
        root /data/site2/;
    }
    
    #client
    echo "192.168.37.7 www.magedu.net www.magedu.tech" > /etc/hosts
    curl http://www.magedu.net
    curl http://www.magedu.tech
    

    小笔记:location

    #server
    vim /etc/nginx/conf.d/test.conf
    server_tokens off;
    server {
        server_name www.magedu.net;
        root /data/site1/;
        location /test {
            root /opt/testdir;
        }
    }
    mkdir /opt/testdir -p
    echo "/opt/testdir/index.html" > /opt/testdir/index.html
    
    #client
    curl http://www.magedu.net/test
    
    #--------------分割线---------------#
    
    #静态资源
    vim /etc/nginx/conf.d/test.conf
    server_tokens off;
    server {
        server_name www.magedu.net;
        root /data/site1/;
        location ~* \.(jpg|gif|html|txt)$ {
            root /opt/static;
        }
        location ~* \.(php|jsp) {
            root /opt/dynamic;
        }
    }
    mkdir /opt/static
    echo a.jsp > /opt/static/a.jsp
    echo aaa.html > /opt/static/a.html
    
    #client
    curl http://www.magedu.net/a.jsp
    
    #--------------分割线---------------#
    
    #别名
    vim /etc/nginx/conf.d/test.conf
    server_tokens off;
    server {
        server_name www.magedu.net;
        root /data/site1/;
        location /about {           #about后面不要加"/"
            alias /opt/testdir;
            index test.html
        }
        error_page 404 /40x.html
        #error_page 404 =200 /404.html  #错误重定向
        location = /40x.html {}
    }
    
    #client
    curl http://www.magedu.net/about
    
    #--------------分割线---------------#
    
    #错误
    vim /etc/nginx/conf.d/test.conf
    server_tokens off;
    server {
        server_name www.magedu.net;
        root /data/site1/;
        error_page 404 /40x.html;
        #error_page 404 =200 /404.html; #错误重定向
        location = /40x.html {}
    }
    
    #--------------分割线---------------#
    
    #try_files
    vim /etc/nginx/conf.d/test.conf
    server_tokens off;
    server {
        server_name www.magedu.net;
        root /data/site1/;
        location /images {
            alias /data/images
            try_files $uri $uri.jpg =404;   #先找uri(uri=/images/{这个值}),再找$uri/defalut.jpg,都找不到就404
        }
    }
    
    #--------------分割线---------------#
    
    #单线程限速
    vim /etc/nginx/conf.d/test.conf
    server_tokens off;
    server {
        server_name www.magedu.net;
        root /data/site1/;
        limit_rate 10k;
    }
    
    #--------------分割线---------------#
    #limit_except
    vim /etc/nginx/conf.d/test.conf
    server_tokens off;
    server {
        server_name www.magedu.net;
        root /data/site1/;
        location / {
            limit_except GET {          #除了get外所有指令都支持
                allow 192.168.37.6;
                deny all;
            }
        }
    }
    
    #client
    curl -I -X OPTIONS www.magedu.net
    curl -I -X GET www.magedu.net
    
    #--------------分割线---------------#
    
    #缓存
    
    

    ngx_http_access_module

    • ngx_http_access_module模块
      可实现基于ip的访问控制功能

    • allow address | CIDR | unix: | all;

    • deny address | CIDR | unix: | all;
      http, server, location, limit_except
      自上而下检查,一旦匹配,将生效,条件严格的置前
      示例:

      location /about {
        root /data/nginx/html/pc;
        index index.html;
        deny 192.168.1.1;
        allow 192.168.1.0/24;
        allow 10.1.1.0/16;
        allow 2001:0db8::/32;
        deny all; #先允许小部分,再拒绝大部分
      } 
      

    ngx_http_auth_basic_module

    • ngx_http_auth_basic_module模块
      实现基于用户的访问控制,使用basic机制进行用户认证

    • auth_basic string | off;

    • auth_basic_user_file file;

      location /admin/ {
        auth_basic "Admin Area";
        auth_basic_user_file /etc/nginx/.ngxpasswd;
      } 
      

      用户口令文件:
      1、明文文本:格式name:password:comment
      2、加密文本:由htpasswd命令实现
      httpd-tools所提供

    ngx_http_stub_status_module

    • ngx_http_stub_status_module模块
      用于输出nginx的基本状态信息, 输出信息示例:
      Active connections: 291
      server accepts handled requests #下面三个数分别对应accepts,handled,requests
      16630948 16630948 31070465
      Reading: 6 Writing: 179 Waiting: 106
      Active connections:当前状态,活动状态的连接数
      accepts:统计总值,已经接受的客户端请求的总数
      handled:统计总值,已处理完成的客户端请求总数,一般和accepts相同,除非拒绝
      requests:统计总值,客户端发来的总的请求数
      Reading:当前状态,正在读取客户端请求报文首部的连接的连接数
      Writing:当前状态,正在向客户端发送响应报文过程中的连接数
      Waiting:当前状态,正在等待客户端发出请求的空闲连接数

    • stub_status示例:

      location /nginx_status {
        stub_status;
        allow 127.0.0.1;
        allow 172.16.0.0/16;
        deny all;
      }  
      

    小笔记:模块

    #访问控制
    vim /etc/nginx/conf.d/test.conf
    server_tokens off;
    server {
      server_name www.magedu.net;
      root /data/site1/;
      location / {    
          allow 192.168.37.6;
          deny all;
      }
    }
    
    #用户的访问控制
    htpasswd -b -c /etc/nginx/conf.d/.nginx_passwd alice centos
    htpasswd -b /etc/nginx/conf.d/.nginx_passwd bob centos
    vim /etc/nginx/conf.d/test.conf
    server_tokens off;
    server {
      server_name www.magedu.net;
      root /data/site1/;
      location /admin {   
          root /data/;
          allow 192.168.37.0/24;
          deny all;
          auth_basic "Admin Area";
          auth_basic_user_file /etc/nginx/conf.d/.nginx_passwd;
      }
    }
    mkdir /data/admin/
    echo /data/admin/index.html > /data/admin/index.html
    
    #client
    http://www.magedu.net/admin
    curl -u bob:centos http://www.magedu.net/admin
    
    #状态页
    vim /etc/nginx/conf.d/test.conf
    server_tokens off;
    server {
      server_name www.magedu.net;
      root /data/site1/;
      location /admin {   
          root /data/;
          allow 192.168.37.0/24;
          deny all;
          auth_basic "Admin Area";
          auth_basic_user_file /etc/nginx/conf.d/.nginx_passwd;
      }
      location /nginx_status {
          stub_status;
          allow 127.0.0.1;
          allow 172.16.0.0/16;
          allow 192.168.37.0/24;
          deny all;
      }  
    }
    
    #client
    ab -c1000 -n 2000 www.magedu.net/m.html
    http://www.magedu.net/nginx_status
    

    nginx 第三方模块

    • 第三模块是对nginx 的功能扩展,第三方模块需要在编译安装nginx 的时候使用参数-- add-module=PATH指定路径添加,有的模块是由公司的开发人员针对业务需求定制 开发的,有的模块是开源爱好者开发好之后上传到github进行开源的模块,nginx支持第三方模块,需要重新编译源码才能支持
    • 开源的echo模块,实现输出变量等信息
      https://github.com/openresty/echo-nginx-module
      示例:
    yum install git –y
    yum install gcc pcre-devel openssl-devel zlib-devel perl-ExtUtils-Embed
    cd /usr/local/src
    git clone https://github.com/openresty/echo-nginx-module.git
    cd nginx-1.16.0/
    useradd –r –s /sbin/nologin nginx
    ./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-http_perl_module \
    --with-pcre \
    --with-stream \
    --with-stream_ssl_module \
    --with-stream_realip_module \
    --add-module=/usr/local/src/echo-nginx-module
    make && make install
    
    vim /apps/nginx/conf/conf.d/pc.conf
    location /test {
        index index.html;
        default_type text/html;
        echo "hello world,main-->";
        echo_reset_timer;
        echo_location /sub1;
        echo_location /sub2;
        echo "took $echo_timer_elapsed sec for total.";
    }
    location /sub1 {
        echo_sleep 1;
        echo sub1;
    }
    location /sub2 {
        echo_sleep 1;
        echo sub2;
    }
    

    小笔记:第三方模块

    #按上面步骤先重新编译nginx
    #1.16 版本不兼容,改用1.14
    
    vim /apps/nginx/conf/nginx.conf
    http{
        include /apps/nginx/conf.d/*.conf;
        ...
    }
    
    vim /apps/nginx/conf.d/test.conf
    server_token off;
    server {
        server_name www.test.com;
        root /data/test;
        location /echo {
            index index.html;
            default_type text/html;
            echo "hello world";
        }
    }
    mkdir -p /data/test/echo
    echo  /data/test/index.html > /data/test/index.html
    echo  /data/test/echo/index.html > /data/test/echo/index.html
    nginx -t
    nginx
    

    nginx 变量使用

    • nginx的变量可以在配置文件中引用,作为功能判断或者日志等场景使用,变量可以分为内置变量和自定义变量,内置变量是由nginx模块自带,通过变量可以获取到众多的与客户端访问相关的值

    • 常见内置变量

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

      $args;#变量中存放了URL中的指令

      http://www.magedu.net/main/index.do?id=090&partner=search

      以上:id=090&partner=search 即为 $args

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

      $cookie_name; #表示key为 name 的cookie值

      $document_uri;#保存了当前请求中不包含指令的URI,注意是不包含请求的指令,如http://www.magedu.net/main/index.do?id=090&partner=search会被定义为/main/index.do

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

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

      $http_cookie;#客户端的cookie信息

      $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;#包含请求参数的原始URI,不包含主机名

      如:main/index.do?id=090&partner=search。

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

      $server_protocol;#请求资源的协议版本,如HTTP/.0,HTTP/.,HTTP/.0等

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

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

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

    • 自定义变量:
      自定义变量名称和值,使用指令set $variable value

    • 格式如下:
      set variable value; 支持:server, location, if 示例: setname magedu;
      echo name; setmy_port server_port; echomy_port;
      echo "server_name:server_port";

    小笔记:变量

    vim /apps/nginx/conf.d/test.conf
    server_token off;
    server {
        server_name www.test.com;
        root /data/test;
        location /echo {
            index index.html;
            default_type text/html;
            echo "hello world";
            echo $remote_addr;
        }
        location /test {
            index index.html;
            default_type text/html;
            echo "hello world,main-->";
            echo_reset_timer;
            echo_location /sub1;
            echo_location /sub2;
            echo "took $echo_timer_elapsed sec for total.";
        }
        location /sub1 {
            echo_sleep 1;
            echo sub1;
        }
        location /sub2 {
            echo_sleep 1;
            echo sub2;
        }
    }
    

    ngx_http_log_module

    • ngx_http_log_module模块
      指定日志格式记录请求
    • log_format name string ...;
      string可以使用nginx核心模块及其它模块内嵌的变量
    • access_log path [format [buffer=size] [gzip[=level]] [flush=time]
      [if=condition]];
      access_log off; #禁用访问日志
      访问日志文件路径,格式及相关的缓冲的配置
      buffer=size
      flush=time

    示例

    log_format compression '$remote_addr-$remote_user [$time_local] '
    '"$request" $status $bytes_sent '
    '"$http_referer" "$http_user_agent" "$gzip_ratio"';
    access_log /spool/logs/nginx-access.log compression buffer=32k;  
    

    小笔记:nginx日志

    #日志位置
    /var/log/nginx/access.log
    
    #自定义访问日志
    vim /etc/nginx/nginx.conf
    http {
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
        log_format  testlog  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" ';                  
        access_log  /var/log/nginx/access.log  main;
        ......
    } 
    vim /etc/nginx/conf.d/test.conf
    server_token off;
    server {
        server_name www.test.com;
        root /data/test;
        location / {}
        access_log /var/log/nginx/magedu_net.access.log testlog;
    }   
    

    自定义json日志格式

    • nginx 的默认访问日志记录内容相对比较单一,默认的格式也不方便后期做日志
      统计分析,生产环境中通常将nginx日志转换为json日志,然后配合使用ELK做日
      志收集-统计-分析
    • json格式的访问日志示例:
      {"@timestamp":"2019-02-
      22T08:55:32+08:00","host":"192.168.7.102","clientip":"192.168.0.1","size":162,"resp
      onsetime":0.000,"upstreamtime":"-","upstreamhost":"-
      ","http_host":"www.magedu.net","uri":"/favicon.ico","domain":"www.magedu.net","xff"
      :"-","referer":"-","tcp_xff":"","http_user_agent":"Mozilla/5.0 (Windows NT 6.1;
      Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0","status":"404"}
    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",'
    '"domain":"$host",'
    '"xff":"$http_x_forwarded_for",'
    '"referer":"$http_referer",'
    '"tcp_xff":"$proxy_protocol_addr",'
    '"http_user_agent":"$http_user_agent",'
    '"status":"$status"}';
    access_log /apps/nginx/logs/access_json.log access_json;
    

    json格式的日志访问统计

    #cat nginx_json.py
    #!/usr/bin/env python
    #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")
    f.close()
    print "状态码200的有--:",len(status_200)
    print "状态码404的有--:",len(status_404)
    
    # python nginx_json.py
    状态码200的有--: 1910
    状态码404的有--: 13
    

    关于favicon.ico

    • favicon.ico 文件是浏览器收藏网址时显示的图标,当使用浏览器访问页面时,浏览器
      会自己主动发起请求获取页面的favicon.ico文件,但是当浏览器请求的favicon.ico文
      件不存在时,服务器会记录404日志,而且浏览器也会显示404报错
    • 解决方案:
    • 服务器不记录访问日志:
    location = /favicon.ico {
        log_not_found off; #文件没发现事件不记录error_log
        access_log off; #不记录access_log
    }
    
    • 将图标保存到指定目录访问:
    #location ~ ^/favicon\.ico$ {
    location = /favicon.ico {
        root /data/nginx/html/pc/images;
    }  
    

    ngx_http_log_module

    • open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];
      open_log_file_cache off;
      缓存各日志文件相关的元数据信息
      max:缓存的最大文件描述符数量
      min_uses:在inactive指定的时长内访问大于等于此值方可被当作活动项
      inactive:非活动时长
      valid:验证缓存中各缓存项是否为活动项的时间间隔

    小笔记:自定义日志格式

    #自定义日志格式
    vim /etc/nginx/nginx.conf
    http {
    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",'
        '"domain":"$host",'
        '"xff":"$http_x_forwarded_for",'
        '"referer":"$http_referer",'
        '"tcp_xff":"$proxy_protocol_addr",'
        '"http_user_agent":"$http_user_agent",'
        '"status":"$status"}';                 
        access_log  /var/log/nginx/access.log  main;
        ......
    } 
    vim /etc/nginx/conf.d/test.conf
    server_token off;
    server {
        server_name www.test.com;
        root /data/test;
        location / {}
        access_log /var/log/nginx/magedu_net.access.log access_json;
    }
    

    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

      配置文件下载服务生产案例

    location /download {
        autoindex on;
        autoindex_exact_size off;
        autoindex_localtime on;
        autoindex_format json;
        limit_rate 100k;
        root /data/nginx/html/pc;
        index index.html;
    }
    mkdir /data/nginx/html/pc/download/
    

    ngx_http_gzip_module

    • ngx_http_gzip_module
      用gzip方法压缩响应数据,节约带宽
    • gzip on | off;
      启用或禁用gzip压缩
    • gzip_comp_level level;
      压缩比由低到高:1 到 9, 默认:1
    • gzip_disable regex ...;
      匹配到客户端浏览器不执行压缩
      示例:gzip_disable "MSIE[1-6].";
    • gzip_min_length length;
      启用压缩功能的响应报文大小阈值
    • gzip_http_version 1.0 | 1.1;
      设定启用压缩功能时,协议的最小版本,默认:1.1
    • gzip_buffers number size;
      支持实现压缩功能时缓冲区数量及每个缓存区的大小
      默认:32 4k 或 16 8k
    • gzip_types mime-type ...;
      指明仅对哪些类型的资源执行压缩操作;即压缩过滤器
      默认包含有text/html,不用显示指定,否则出错
    • gzip_vary on | off;
      如果启用压缩,是否在响应报文首部插入“Vary: Accept-Encoding”
    • gzip_proxied off | expired | no-cache | no-store | private |
      no_last_modified | no_etag | auth | any ...;
      nginx充当代理服务器时,对于后端服务器的响应报文,在何种条件下启
      用压缩功能
      off:不启用压缩
      expired,no-cache, no-store,private:对后端服务器的响应报文首部
      Cache-Control值任何一个,启用压缩功能

    示例:

    gzip on;
    gzip_comp_level 6;
    gzip_min_length 64;
    gzip_vary on;
    gzip_types text/xml text/css application/javascript; 
    

    小笔记:充当文件下载服务

    vim /etc/nginx/conf.d/test.conf
    server {
        server_name www.test.com;
        root /data/test;
        location / {}
        access_log /var/log/nginx/test.com.access.log access_json;
    
        location /download {
            autoindex on;
            autoindex_exact_size off;
            autoindex_localtime on;
            #autoindex_format json;     #html|xml|json|jsonp
            limit_rate 100k;
            index index.html;
        }
    }
    mkdir /data/test/download
    mount /dev/sr0 /data/test/download
    

    小笔记:压缩

    vim /etc/nginx/conf.d/test.conf
    server {
        server_name www.test.com;
        root /data/test;
        location / {}
        access_log /var/log/nginx/magedu_net.access.log access_json;
        gzip on;                #启用压缩
        gzip_comp_level 6;      #压缩等级
        gzip_min_length 64;     #响应报文阈值
        gzip_vary on;           #响应报文首部插入“Vary: Accept-Encoding”  
        gzip_types text/xml text/css application/javascript;    #压缩类型
    }
    
    #client
    curl --compressed http://www.magedu.net/m.html
    

    相关文章

      网友评论

          本文标题:32-高性能WEB服务NGINX(一)

          本文链接:https://www.haomeiwen.com/subject/pcvvwhtx.html