做网站销售经常遇到的问题,公司排名seo,wordpress中英文网站,杭州app开发公司哪家好目录
1 Web 服务基础介绍
1.1 Web 服务介绍
1.1.1 Apache 经典的 Web 服务端
1.1.2 Nginx-高性能的 Web 服务端
1.1.3 用户访问体验和性能
1.1.4 服务端 I/O 流程
1.2 I/O 模型
1.2.1 I/O 模型相关概念
1.2.2 网络 I/O 模型
1.2.3 五种 IO 对比
1.2.4 I/O 的具体实现…目录
1 Web 服务基础介绍
1.1 Web 服务介绍
1.1.1 Apache 经典的 Web 服务端
1.1.2 Nginx-高性能的 Web 服务端
1.1.3 用户访问体验和性能
1.1.4 服务端 I/O 流程
1.2 I/O 模型
1.2.1 I/O 模型相关概念
1.2.2 网络 I/O 模型
1.2.3 五种 IO 对比
1.2.4 I/O 的具体实现方式
2 Nginx 架构和安装
2.1 Nginx 概述
2.1.1 Nginx 介绍
2.1.2 Nginx 功能介绍
2.1.3 基础特性
2.2 Nginx 架构和进程
2.2.1 Nginx 进程结构
2.2.2 Nginx 进程间通信
2.2.3 Nginx 启动和 HTTP 连接建立
2.3 Nginx 模块介绍 2.4 核心配置详细
2.4.1 配置文件说明
2.4.2默认配置文件格式说明
2.4.3 全局配置
3 实验案例和示例
3.1 Nginx 的安装与升级
3.1.1 Nginx版本和安装方式
3.1.2 Nginx 编译安装
3.1.3 设置环境变量和启动文件
3.1.4 平滑升级和回滚
3.2 高并发配置
3.3 建立首个web站点
3.4 root与alias
3.5 用户认证访问
3.6 自定义错误页面
3.7 自定义日志
3.8 文件检测
3.9 长连接配置
3.10 下载服务器部署
3.11 nginx状态页
3.12 网页压缩功能
3.13 Nginx 变量使用
3.14 rewrite模块
3.14.1 if指令
3.14.2 set 指令
3.14.3 break 指令
3.14.4 return 指令
3.14.5 rewrite指令
3.14.6 rewrite实现全站加密
3.14.7 不存在页面重定向
3.15 防盗链
3.16 反向代理实现动静分离
3.17 反向代理缓存功能
3.18 四层负载
3.19 部署fastcgi泵整合nginx
3.20 利用memcache加速php
3.21 memcache实现高速缓存
3.22 nginx二次开发版本 1 Web 服务基础介绍
正常情况下的单次web服务访问流程1.1 Web 服务介绍
1.1.1 Apache 经典的 Web 服务端
Apache起初由美国的伊利诺伊大学香槟分校的国家超级计算机应用中心开发目前经历了两大版本分别是1.X和2.X其可以通过编译安装实现特定的功能1Apache prefork 模型预派生模式有一个主控制进程然后生成多个子进程使用select模型最大并发1024每个子进程有一个独立的线程响应用户请求 相对比较占用内存但是比较稳定可以设置最大和最小进程数 是最古老的一种模式,也是最稳定的模式适用于访问量不是很大的场景 优点稳定 缺点每个用户请求需要对应开启一个进程,占用资源较多并发性差,不适用于高并发场景2Apache worker 模型
有一个控制进程启动多个子进程 每个子进程里面包含固定的线程 使用线程来处理请求 当线程不够使用的时候会再启动一个新的子进程,然后在进程里面再启动线程处理请求由于其使用了线程处理请求因此可以承受更高的并发
优点相比prefork 占用的内存较少可以同时处理更多的请求 缺点使用keepalive的长连接方式某个线程会一直被占据即使没有传输数据也需要一直等待到超时才会被释放。如果过多的线程被这样占据也会导致在高并发场景下的无服务线程可用该问题在prefork模式下同样会发生3Apache event模型Apache中最新的模式2012年发布的apache 2.4.X系列正式支持event 模型,属于事件驱动模型(epoll)每个进程响应多个请求在现在版本里的已经是稳定可用的模式。它和worker模式很像最大的区别在于它解决了keepalive场景下长期被占用的线程的资源浪费问题某些线程因为被keepalive空挂在哪里等待中间几乎没有请求过来甚至等到超时 event MPM中会有一个专门的线程来管理这些keepalive类型的线程 当有真实请求过来的时候将请求传递给服务线程执行完毕后又允许它释放。这样增强了高并发场景下的请求处理能力 优点单线程响应多请求占据更少的内存高并发下表现更优秀会有一个专门的线程来管理keep-alive类型的线程当有真实请求过来的时候将请求传递给服务线程执行完毕后又允许它释放 缺点没有线程安全控制 1.1.2 Nginx-高性能的 Web 服务端
官网地址www.nginx.orgNginx历经十几年的迭代更新https://nginx.org/en/CHANGES目前功能已经非常完善且运行稳 定另外Nginx的版本分为开发版、稳定版和过期版nginx以功能丰富著称它即可以作为http服务器也可以作为反向代理服务器或者邮件服务器能够快速的响应静态网页的请求。 支持FastCGI/SSL/Virtual Host/URL Rwrite /Gzip / HTTP Basic Auth/http或者TCP的负载均衡(1.9版本以上且开启stream模块)等功能并且支持第三方的功能扩展。 天猫淘宝京东小米 163 新浪等一线互联网公司都在用Nginx或者进行二次开发 基于Nginx的工作场景 1.1.3 用户访问体验和性能
1用户访问体验统计互联网存在用户速度体验的1-3-10原则即1秒最优1-3秒较优3~10秒比较慢10秒以上用户无法接受。用户放弃一个产品的代价很低只是换一个URL而已。 全球最大搜索引擎 Google慢500ms 20% 将放弃访问。全球最大的电商零售网站亚马逊慢100ms 1% 将放弃交易有很多研究都表明性能对用户的行为有很大的影响 79%的用户表示不太可能再次打开一个缓慢的网站 47%的用户期望网页能在2秒钟以内加载 40%的用户表示如果加载时间超过三秒钟就会放弃这个网站 页面加载时间延迟一秒可能导致转换损失7%页面浏览量减少11% 8秒定律用户访问一个网站时如果等待网页打开的时间超过8秒会有超过30%的用户放弃等待 2影响用户体验的因素 据说马云在刚开始创业在给客户演示时打开一个网站花了不到四个小时 影响用户体验的因素 1.客户端 客户端硬件配置 客户端网络速率 客户端与服务端距离 2.服务器服务端网络速率 服务端硬件配置 服务端架构设计 服务端应用程序工作模式 服务端并发数量服务端响应文件大小及数量 buffer cache服务端I/O压力1.2.4 服务端 I/O 流程
1.1.4 服务端 I/O 流程
I/O在计算机中指Input/Output IOPS (Input/Output Per Second)即每秒的输入输出量(或读写次数)是衡量磁盘性能的主要指标之一。IOPS是指单位时间内系统能处理的I/O请求数量一般以每秒处理的 I/O请求数量为单位I/O请求通常为读或写数据操作请求。 一次完整的I/O是用户空间的进程数据与内核空间的内核数据的报文的完整交换但是由于内核空间与用户空间是严格隔离的所以其数据交换过程中不能由用户空间的进程直接调用内核空间的内存数据而是需要经历一次从内核空间中的内存数据copy到用户空间的进程内存当中所以简单说I/O就是把数据从内核空间中的内存数据复制到用户空间中进程的内存当中。 服务器的I/O磁盘I/O 网络I/O : 一切皆文件,本质为对socket文件的读写 1磁盘 I/O磁盘I/O是进程向内核发起系统调用请求磁盘上的某个资源比如是html 文件或者图片然后内核通过相应的驱动程序将目标文件加载到内核的内存空间加载完成之后把数据从内核内存再复制给进程内存如果是比较大的数据也需要等待时间 2 网络 I/O 网络通信就是网络协议栈到用户空间进程的IO就是网络IO 网络I/O 处理过程 获取请求数据客户端与服务器建立连接发出请求服务器接受请求1-3 构建响应当服务器接收完请求并在用户空间处理客户端的请求直到构建响应完成4返回数据服务器将已构建好的响应再通过内核空间的网络 I/O 发还给客户端5-7 不论磁盘和网络I/O每次I/O都要经由两个阶段第一步将数据从文件先加载至内核内存空间缓冲区等待数据准备完成时间较长 第二步将数据从内核缓冲区复制到用户空间的进程的内存中时间较短 1.2 I/O 模型 1.2.1 I/O 模型相关概念 同步/异步关注的是消息通信机制即调用者在等待一件事情的处理结果时被调用者是否提供完成状态的通知。 同步synchronous被调用者并不提供事件的处理结果相关的通知消息需要调用者主动询问事 情是否处理完成 异步asynchronous被调用者通过状态、通知或回调机制主动通知调用者被调用者的运行状态 阻塞/非阻塞关注调用者在等待结果返回之前所处的状态阻塞blocking指IO操作需要彻底完成后才返回到用户空间调用结果返回之前调用者被挂 起干不了别的事情。 非阻塞nonblocking指IO操作被调用后立即返回给用户一个状态值而无需等到IO操作彻底完 成在最终的调用结果返回之前调用者不会被挂起可以去做别的事情。 1.2.2 网络 I/O 模型
阻塞型、非阻塞型、复用型、信号驱动型、异步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是否完成这种方式简单但是比较慢用的比较少。 2非阻塞型 I/O 模型 (nonblocking IO)用户线程发起IO请求时立即返回。但并未读取到任何数据用户线程需要不断地发起IO请求直到数据到达后才真正读取到数据继续执行。即 “轮询”机制存在两个问题如果有大量文件描述符都要等那么就得一个一个的read。这会带来大量的Context Switchread是系统调用每调用一次就得在用户态和核心态切换一次。轮询的时间不好把握。这里是要猜多久之后数据才能到。等待时间设的太长程序响应延迟就过大;设的太短就会造成过于频繁的重试干耗CPU而已是比较浪费CPU的方式一般很少直接使用这种模型而是在其他IO模型中使用非阻塞IO这一特性。
非阻塞程序向内核发送请I/O求后一直等待内核响应如果内核处理请求的IO操作不能立即返回IO结果进程将不再等待而且继续处理其他请求但是仍然需要进程隔一段时间就要查看内核I/O是否完成。 查看上图可知在设置连接为非阻塞时当应用进程系统调用 recvfrom 没有数据返回时内核会立即返回一个 EWOULDBLOCK 错误而不会一直阻塞到数据准备好。如上图在第四次调用时有一个数据报准备好了所以这时数据会被复制到应用进程缓冲区于是 recvfrom 成功返回数据 当一个应用进程这样循环调用 recvfrom 时称之为轮询 polling 。这么做往往会耗费大量CPU时间实际使用很少 3多路复用 I/O 型(I/O multiplexing)上面的模型中,每一个文件描述符对应的IO是由一个线程监控和处理
多路复用IO指一个线程可以同时实际是交替实现即并发完成监控和处理多个文件描述符对应各自的IO即复用同一个线程 一个线程之所以能实现同时处理多个IO,是因为这个线程调用了内核中的SELECT,POLL或EPOLL等系统调用从而实现多路复用IO I/O multiplexing 主要包括:selectpollepoll三种系统调用select/poll/epoll的好处就在于单个 process就可以同时处理多个网络连接的IO。 它的基本原理就是select/poll/epoll这个function会不断的轮询所负责的所有socket当某个socket有数据到达了就通知用户进程。 当用户进程调用了select那么整个进程会被block而同时kernel会“监视”所有select负责的socket当任何一个socket中的数据准备好了select就会返回。这个时候用户进程再调用read操作将数据从kernel拷贝到用户进程。 Apache prefork是此模式的selectworker是poll模式。 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 优点可以基于一个阻塞对象同时在多个描述符上等待就绪而不是使用多个线程(每个文件描述符一个线程)这样可以大大节省系统资源 缺点当连接数较少时效率相比多线程阻塞 I/O 模型效率较低可能延迟更大因为单个连接处理需要 2 次系统调用占用时间会有增加 IO多路复用适用如下场合 当客户端处理多个描述符时一般是交互式输入和网络套接口必须使用I/O复用当一个客户端同时处理多个套接字时此情况可能的但很少出现 当一个服务器既要处理监听套接字又要处理已连接套接字一般也要用到I/O复用当一个服务器即要处理TCP又要处理UDP一般要使用I/O复用 当一个服务器要处理多个服务或多个协议一般要使用I/O复用 4信号驱动式 I/O 模型 (signal-driven IO)信号驱动I/O的意思就是进程现在不用傻等着也不用去轮询。而是让内核在数据就绪时发送信号通知进程。
调用的步骤是通过系统调用 sigaction 并注册一个信号处理的回调函数该调用会立即返回然后主
程序可以继续向下执行当有I/O操作准备就绪,即内核数据就绪时内核会为该进程产生一个 SIGIO信 号并回调注册的信号回调函数这样就可以在信号回调函数中系统调用 recvfrom 获取数据,将用户进程所需要的数据从内核空间拷贝到用户空间
此模型的优势在于等待数据报到达期间进程不被阻塞。用户主程序可以继续执行只要等待来自信号处理函数的通知。
在信号驱动式 I/O 模型中应用程序使用套接口进行信号驱动 I/O并安装一个信号处理函数进程继续运行并不阻塞
当数据准备好时进程会收到一个 SIGIO 信号可以在信号处理函数中调用 I/O 操作函数处理数据。
优点线程并没有在等待数据时被阻塞内核直接返回调用接收信号不影响进程继续处理其他请求因此可以提高资源的利用率 缺点信号 I/O 在大量 IO 操作时可能会因为信号队列溢出导致没法通知 异步阻塞程序进程向内核发送IO调用后不用等待内核响应可以继续接受其他请求内核收到进程请求后进行的IO如果不能立即返回就由内核等待结果直到IO完成后内核再通知进程。 5异步 I/O 模型 (asynchronous IO)异步I/O 与信号驱动I/O最大区别在于信号驱动是内核通知用户进程何时开始一个I/O操作而异步I/O是由内核通知用户进程I/O操作何时完成两者有本质区别,相当于不用去饭店场吃饭直接点个外卖把等待上菜的时间也给省了 相对于同步I/O异步I/O不是顺序执行。用户进程进行aio_read系统调用之后无论内核数据是否准备好都会直接返回给用户进程然后用户态进程可以去做别的事情。等到socket数据准备好了内核直接复制数据给进程然后从内核向进程发送通知。IO两个阶段进程都是非阻塞的。 信号驱动IO当内核通知触发信号处理程序时信号处理程序还需要阻塞在从内核空间缓冲区拷贝数据到用户空间缓冲区这个阶段而异步IO直接是在第二个阶段完成后内核直接通知用户线程可以进行后续操作了 优点异步 I/O 能够充分利用 DMA 特性让 I/O 操作与计算重叠 缺点要实现真正的异步 I/O操作系统需要做大量的工作。目前 Windows 下通过 IOCP 实现了真正的异步 I/O在 Linux 系统下Linux 2.6才引入目前 AIO 并不完善因此在 Linux 下实现高并发网络编程时以 IO 复用模型模式多线程任务的架构基本可以满足需求 Linux提供了AIO库函数实现异步但是用的很少。目前有很多开源的异步IO库例如libevent、libev、libuv。 异步非阻塞程序进程向内核发送IO调用后不用等待内核响应可以继续接受其他请求内核调用的IO如果不能立即返回内核会继续处理其他事物直到IO完成后将结果通知给内核内核在将IO完成的结果返回给进程期间进程可以接受新的请求内核也可以处理新的事物因此相互不影响可以实现较大的同时并实现较高的IO复用因此异步非阻塞使用最多的一种通信方式。 1.2.3 五种 IO 对比
这五种 I/O 模型中越往后阻塞越少理论上效率也是最优。前四种属于同步 I/O因为其中真正的 I/O操作(recvfrom)将阻塞进程/线程只有异步 I/O 模型才与 POSIX 定义的异步 I/O 相匹配1.2.4 I/O 的具体实现方式
1 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、kqueue 用于支持BSD系列平台的高校事件驱动模型主要用在FreeBSD 4.1及以上版本、OpenBSD 2.0级以上版本NetBSD级以上版本及Mac OS X 平台上该模型也是poll库的变种因此和epoll没有本质上的区别都是通过避免轮询操作提供效率。 5、Iocp Windows系统上的实现方式对应第5种异步I/O模型。 6、rtsig 不是一个常用事件驱动最大队列1024不是很常用 7、/dev/poll: 用于支持unix衍生平台的高效事件驱动模型主要在Solaris 平台、HP/UX该模型是sun公司在开发 Solaris系列平台的时候提出的用于完成事件驱动机制的方案它使用了虚拟的/dev/poll设备开发人员将要见识的文件描述符加入这个设备然后通过ioctl()调用来获取事件通知因此运行在以上系列平台的时候请使用/dev/poll事件驱动机制。 8、eventport 该方案也是sun公司在开发Solaris的时候提出的事件驱动库只是Solaris 10以上的版本该驱动库看防止内核崩溃等情况的发生。 2常用I/O模型比较 Select POSIX所规定目前几乎在所有的平台上支持其良好跨平台支持也是它的一个优点本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理 缺点 单个进程能够监视的文件描述符的数量存在最大限制在Linux上一般为1024可以通过修改宏定 FD_SETSIZE再重新编译内核实现但是这样也会造成效率的降低单个进程可监视的fd数量被限制默认是1024修改此值需要重新编译内核对socket是线性扫描即采用轮询的方法效率较低select 采取了内存拷贝方法来实现内核将 FD 消息通知给用户空间这样一个用来存放大量fd的数据结构这样会使得用户空间和内核空间在传递该结构时复制开销大 poll 本质上和select没有区别它将用户传入的数组拷贝到内核空间然后查询每个fd对应的设备状态其没有最大连接数的限制原因是它是基于链表来存储的大量的fd的数组被整体复制于用户态和内核地址空间之间而不管这样的复制是不是有意义poll特点是“水平触发”如果报告了fd后没有被处理那么下次poll时会再次报告该fd select是边缘触发即只通知一次 epoll 在Linux 2.6内核中提出的select和poll的增强版本支持水平触发LT和边缘触发ET最大的特点在于边缘触发它只告诉进程哪些fd刚刚变为就需态并且只会通知一次使用“事件”的就绪通知方式通过epoll_ctl注册fd一旦该fd就绪内核就会采用类似callback的回调机制来激活该fdepoll_wait便可以收到通知 优点: 没有最大并发连接的限制能打开的FD的上限远大于1024(1G的内存能监听约10万个端口)具体查看/proc/sys/fs/file-max此值和系统内存大小相关 效率提升非轮询的方式不会随着FD数目的增加而效率下降;只有活跃可用的FD才会调用callback函 数即epoll最大的优点就在于它只管理“活跃”的连接而跟连接总数无关 内存拷贝利用mmap(Memory Mapping)加速与内核空间的消息传递;即epoll使用mmap减少复制开销 总结: 1、epoll只是一组API比起select这种扫描全部的文件描述符epoll只读取就绪的文件描述符再加入基于事件的就绪通知机制所以性能比较好 2、基于epoll的事件多路复用减少了进程间切换的次数使得操作系统少做了相对于用户任务来说的无用功。 3、epoll比select等多路复用方式来说减少了遍历循环及内存拷贝的工作量因为活跃连接只占总并发连接的很小一部分。 实例最大并发连接数和内存有直接关系 1.3 零拷贝
1.3.1 零拷贝介绍
传统 Linux中 I/O 的问题 传统的 Linux 系统的标准 I/O 接口read、write是基于数据拷贝的也就是数据都是copy_to_user或者 copy_from_user这样做的好处是通过中间缓存的机制减少磁盘 I/O 的操作但是坏处也很明显大量数据的拷贝用户态和内核态的频繁切换会消耗大量的 CPU 资源严重影响数据传输的性能统计表明在Linux协议栈中数据包在内核态和用户态之间的拷贝所用的时间甚至占到了数据包整个处理流程时间的57.1%
什么是零拷贝
零拷贝就是上述问题的一个解决方案通过尽量避免拷贝操作来缓解 CPU 的压力。零拷贝并没有真正做到“0”拷贝它更多是一种思想很多的零拷贝技术都是基于这个思想去做的优化
1.3.2 零拷页相关技术1MMAP ( Memory Mapping ) mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后进程可以向访问普通内存一样对文件进行访问。 mmap是一种内存映射文件的方法即将一个文件或者其它对象映射到进程的地址空间实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。 实现这样的映射关系后进程就可以采用指针的方式读写操作这一段内存而系统会自动回写脏页面到对应的文件磁盘上即完成了对文件的操作而不必再调用read,write等系统调用函数。相反内核空间对这段区域的修改也直接反映用户空间从而可以实现不同进程间的文件共享。 内存映射减少数据在用户空间和内核空间之间的拷贝操作,适合大量数据传输 上面左图为传统读写,右图为MMAP.两者相比mmap要比普通的read系统调用少了一次copy的过程。因为read调用进程是无法直接访问kernel space的所以在read系统调用返回前内核需要将数据从内核复制到进程指定的buffer。但mmap之后进程可以直接访问mmap的数据(page cache)。
2 SENDFILE 3 DMA 辅助的 SENDFILE2 Nginx 架构和安装
2.1 Nginx 概述
2.1.1 Nginx 介绍
Nginxengine X 2002年开发分为社区版和商业版(nginx plus )
Nginx是免费的、开源的、高性能的HTTP和反向代理服务器、邮件代理服务器、以及TCP/UDP代理服务器
解决C10K问题10K Connections
Nginx官网http://nginx.org
nginx的其它的二次发行版
Tengine由淘宝网发起的Web服务器项目。它在Nginx的基础上针对大访问量网站的需求添加了很多高级功能和特性。Tengine的性能和稳定性已经在大型的网站如淘宝网天猫商城等得到了很好的检验。它的最终目标是打造一个高效、稳定、安全、易用的Web平台。从2011年12月开始Tengine成为一个开源项目官网: http://tengine.taobao.org/ OpenResty基于 Nginx 与 Lua 语言的高性能 Web 平台章亦春团队开发官网http://openresty.org/cn/
2.1.2 Nginx 功能介绍
静态的web资源服务器html图片jscsstxt等静态资源http/https协议的反向代理 结合FastCGI/uWSGI/SCGI等协议反向代理动态资源请求 tcp/udp协议的请求转发反向代理 imap4/pop3协议的反向代理
2.1.3 基础特性
模块化设计较好的扩展性 高可靠性 支持热部署不停机更新配置文件升级版本更换日志文件 低内存消耗10000个keep-alive连接模式下的非活动连接仅需2.5M内存event-driven,aio,mmapsendfile
2.1.4 Web 服务相关的功能虚拟主机server 支持 keep-alive 和管道连接(利用一个连接做多次请求)访问日志支持基于日志缓冲提高其性能url rewirte 路径别名 基于IP及用户的访问控制 支持速率限制及并发数限制 重新配置和在线升级而无须中断客户的工作进程 2.2 Nginx 架构和进程 2.2.1 Nginx 进程结构
web请求处理机制多进程方式服务器每接收到一个客户端请求就有服务器的主进程生成一个子进程响应客户端直到用户关闭连接这样的优势是处理速度快子进程之间相互独立但是如果访问过大会导致服务器资源耗尽而无法提供请求 多线程方式与多进程方式类似但是每收到一个客户端请求会有服务进程派生出一个线程和此客户端进行交互一个线程的开销远远小于一个进程因此多线程方式在很大程度减轻了web服务器对系统资源的要求但是多线程也有自己的缺点即当多个线程位于同一个进程内工作的时候可以相互访问同样的内存地址空间所以他们相互影响一旦主进程挂掉则所有子线程都不能工作了IIS服务器使用了多线程的方式需要间隔一段时间就重启一次才能稳定。 Nginx是多进程组织模型而且是一个由Master主进程和Worker工作进程组成。主进程(master process)的功能对外接口接收外部的操作信号 对内转发根据外部的操作的不同通过信号管理 Worker 监控监控 worker 进程的运行状态worker 进程异常终止后自动重启 worker 进程读取Nginx 配置文件并验证其有效性和正确性 建立、绑定和关闭socket连接 按照配置生成、管理和结束工作进程 接受外界指令比如重启、升级及退出服务器等指令 不中断服务实现平滑升级重启服务并应用新的配置 开启日志文件获取文件描述符 不中断服务实现平滑升级升级失败进行回滚处理 编译和处理perl脚本 工作进程worker process的功能所有 Worker 进程都是平等的 实际处理网络请求由 Worker 进程处理 Worker进程数量一般设置为核心数充分利用CPU资源同时避免进程数量过多导致进程竞争CPU资源增加上下文切换的损耗 接受处理客户的请求 将请求依次送入各个功能模块进行处理 I/O调用获取响应数据 与后端服务器通信接收后端服务器的处理结果 缓存数据访问缓存索引查询和调用缓存数据 发送请求结果响应客户的请求 接收主程序指令比如重启、升级和退出等 2.2.2 Nginx 进程间通信
工作进程是由主进程生成的主进程使用fork()函数进程镜像在Nginx服务器启动过程中主进程根据配置文件决定启动工作进程的数量然后建立一张全局的工作表用于存放当前未退出的所有的工作进程主进程生成工作进程后会将新生成的工作进程加入到工作进程表中并建立一个单向的管道并将其传递给工作进程该管道与普通的管道不同它是由主进程指向工作进程的单向通道包含了主进程向工作进程发出的指令、工作进程ID、工作进程在工作进程表中的索引和必要的文件描述符等信息。
主进程与外界通过信号机制进行通信当接收到需要处理的信号时它通过管道向相关的工作进程发送正确的指令每个工作进程都有能力捕获管道中的可读事件当管道中有可读事件的时候工作进程就会从管道中读取并解析指令然后采取相应的执行动作这样就完成了主进程与工作进程的交互。
worker进程之间的通信原理基本上和主进程与worker进程之间的通信是一样的只要worker进程之间能够取得彼此的信息建立管道即可通信但是由于worker进程之间是完全隔离的因此一个进程想要知道另外一个进程的状态信息,就只能通过主进程来实现。
为了实现worker进程之间的交互master进程在生成worker进程之后在worker进程表中进行遍历将该新进程的PID以及针对该进程建立的管道句柄传递给worker进程中的其他进程为worker进程之间的通信做准备当worker进程1向worker进程2发送指令的时候首先在master进程给它的其他worker进程工作信息中找到2的进程PID然后将正确的指令写入指向进程2的管道worker进程2捕获到管道中的事件后解析指令并进行相关操作这样就完成了worker进程之间的通信。
另外worker进程可以通过共享内存来通讯的比如upstream中的zone或者limit_req、limit_conn中的zone等。操作系统提供了共享内存机制 2.2.3 Nginx 启动和 HTTP 连接建立 Nginx 启动时Master 进程加载配置文件 Master 进程初始化监听的 socket Master 进程fork 出多个 Worker 进程 Worker 进程竞争新的连接获胜方通过三次握手建立 Socket 连接并处理请求
2.3 Nginx 模块介绍
nginx 有多种模块核心模块是 Nginx 服务器正常运行必不可少的模块提供错误日志记录、配置文件解析、事件驱动机制、进程管理等核心功能 标准HTTP模块提供 HTTP 协议解析相关的功能比如端口配置、网页编码设置、 HTTP响应头设置等等 可选HTTP模块主要用于扩展标准的 HTTP 功能让 Nginx 能处理一些特殊的服务比如 Flash 多媒体传输、解析 GeoIP 请求、网络传输压缩、安全协议 SSL 支持等 邮件服务模块主要用于支持 Nginx 的邮件服务包括对 POP3 协议、 IMAP 协议和 SMTP协议的支持 Stream服务模块: 实现反向代理功能,包括TCP协议代理 第三方模块是为了扩展 Nginx 服务器应用完成开发者自定义功能比如 Json 支持、 Lua 支持等 2.4 核心配置详细
2.4.1 配置文件说明 nginx 官方帮助文档http://nginx.org/en/docs/ Nginx的配置文件的组成部分 主配置文件nginx.conf 子配置文件: include conf.d/*.conf fastcgi uwsgiscgi 等协议相关的配置文件 mime.types支持的mime类型MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型MIME消息能包含文本、图像、音频、视频以及其他应用程序专用的数据是设定某种扩展名的文件用一种应用程序来打开的方式类型当该扩展名文件被访问的时候浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名以及一些媒体文件打开方式。 nginx配置文件格式说明 配置文件由指令与指令块构成 每条指令以;分号结尾指令与值之间以空格符号分隔 可以将多条指令放在同一行,用分号分隔即可,但可读性差,不推荐指令块以{}大括号将多条指令组织在一起,且可以嵌套指令块 include语句允许组合多个配置文件以提升可维护性 使用#符号添加注释提高可读性 使用$符号使用变量 部分指令的参数支持正则表达式 Nginx 主配置文件的配置指令方式主配置文件结构四部分main block主配置段即全局配置段对http,mail都有效
#事件驱动相关的配置
event {
...
}
#http/https 协议相关配置段
http {
...
}
#默认配置文件不包括下面两个块
#mail 协议相关配置段
mail {
...
}
#stream 服务器相关配置段
stream {
...
} 2.4.2默认配置文件格式说明 #全局配置端对全局生效主要设置nginx的启动用户/组启动的工作进程数量工作模式Nginx的PID路
径日志路径等。
user nginx nginx;
worker_processes 1; #启动工作进程数数量----块分隔符----
events { #events #设置快主要影响nginx服务器与用户的网络连接比如是否允许同时接受多个网络连接使用哪种事件驱动模型 #处理请求每个工作进程可以同时支持的最大连接数是否开启对多工作进程下的网络连接进行序列化等。
worker_connections 1024; #设置单个nginx工作进程可以接受的最大并发
#作为web服务器的时候最大并发数为 #worker_connections * worker_processes
#作为反向代理的时候为(worker_connections * worker_processes)/2
}
----块分隔符----http { #http块是Nginx服务器配置中的重要部分缓存、代理和日志格式定义等绝大多数功能和第三方模块都 #可以在这设置http块可以包含多个server块而一个server块中又可以包含多个location块
#server块可以配置文件引入、MIME-Type定义、日志自定义、是否启用sendfile、连接超时时间和 #单个链接的请求上限等。
include mime.types;
default_type application/octet-stream;
sendfile on; #作为web服务器的时候打开sendfile加快静态文件传输指定是否使用
#sendfile系统调用来传输文件
#sendfile系统调用在两个文件描述符之间直接传递数据(完全在内核中操作)
#从而避免了数据在内核缓冲区和用户缓冲区之间的拷贝操作效率很高被称之为零拷贝
#硬盘 kernel buffer (快速拷贝到kernelsocketbuffer) 协议栈。keepalive_timeout 65; #长连接超时时间单位是秒server { #设置一个虚拟机主机可以包含自己的全局快同时也可以包含多个location模块
#比如本虚拟机监听的端口、本虚拟机的名称和IP配置多个server可以使用一个端口比如都使用 #80端口提供web服务listen 80; #配置server监听的端口
server_name localhost; #本server的名称当访问此名称的时候nginx会调用当前serevr
内部的配置进程匹配。
location / { #location其实是server的一个指令为nginx服务器提供比较
多而且灵活的指令
#都是在location中体现的主要是基于nginx接受到的请求字符
串
#对用户请求的UIL进行匹配并对特定的指令进行处理
#包括地址重定向、数据缓存和应答控制等功能都是在这部分实现
#另外很多第三方模块的配置也是在location模块中配置。
root html; #相当于默认页面的目录名称默认是安装目录的相对路径可以使
用绝对路径配置。
index index.html index.htm; #默认的页面文件名称}
error_page 500 502 503 504 /50x.html; #错误页面的文件名称
location /50x.html { #location处理对应的不同错误码的页面定
义到/50x.html
#这个跟对应其server中定义的目录下。
root html; #定义默认页面所在的目录}}#和邮件相关的配置
#mail {
# ...
# } mail 协议相关配置段
#tcp代理配置1.9版本以上支持
#stream {
# ...
# } stream 服务器相关配置段
#导入其他路径的配置文件
#include /apps/nginx/conf.d/*.conf
} 2.4.3 全局配置 Main 全局配置段常见的配置指令分类 正常运行必备的配置 优化性能相关的配置 用于调试及定位问题相关的配置 事件驱动相关的配置 全局配置说明user nginx nginx; #启动Nginx工作进程的用户和组
worker_processes [number | auto]; #启动Nginx工作进程的数量,一般设为和CPU核心数相同worker_cpu_affinity 00000001 00000010 00000100 00001000 | auto ;
#将Nginx工作进程绑定到指定的CPU核心默认Nginx是不进行进程绑定的绑定并不是意味着当前nginx进
程独占以一核心CPU但是可以保证此进程不运行在其他核心上这就极大减少了nginx的工作进程在不同的
cpu核心上的来回跳转减少了CPU对进程的资源分配与回收以及内存管理等因此可以有效的提升nginx服务
器的性能。CPU MASK: 000000010号CPU
000000101号CPU
100000007号CPU#示例
worker_cpu_affinity 0001 0010 0100 1000;第0号---第3号CPU
worker_cpu_affinity 0101 1010;
#示例
worker_processes 4;
worker_cpu_affinity 00000010 00001000 00100000 10000000;[rootcentos8 ~]# ps axo pid,cmd,psr | grep nginx
31093 nginx: master process /apps 1
34474 nginx: worker process 1
34475 nginx: worker process 3
34476 nginx: worker process 5
34477 nginx: worker process 7#错误日志记录配置语法error_log file [debug | info | notice | warn | error | crit
| alert | emerg]#error_log logs/error.log;
#error_log logs/error.log notice;
error_log /usr/local/nginx/logs/error.log error;#pid文件保存路径
pid /usr/local/nginx/logs/nginx.pid;
worker_priority 0; #工作进程优先级-20~20(19)
worker_rlimit_nofile 65536; #所有worker进程能打开的文件数量上限,
#包括:Nginx的所有连接例如与代理服务器的连接等
#而不仅仅是与客户端的连接
#另一个考虑因素是实际的并发连接数不能超过系统级别的最大打开文件数的限制
#最好与ulimit -n 或者limits.conf的值保持一致,#修改pam限制
[rootNginx ~]# sudo -u nginx ulimit -n
1024
[rootNginx ~]# vim /etc/security/limits.conf
* - nofile 100000[rootNginx ~]# sudo -u nginx ulimit -n
100000
daemon off; #前台运行Nginx服务用于测试、docker等环境。
master_process off|on; #是否开启Nginx的master-worker工作模式仅用于开发调试场景,默认为onevents {
worker_connections 65535; #设置单个工作进程的最大并发连接数
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
} 3 实验案例和示例 实验环境介绍 webservera #eth0 172.25.254.10 RS1 #eth0 172.25.254.100 RS2 #eth0 172.25.254.200 火墙全部关闭 3.1 Nginx 的安装与升级 3.1.1 Nginx版本和安装方式 Nginx版本 Mainline version 主要开发版本,一般为奇数版本号,比如1.19 Stable version 当前最新稳定版,一般为偶数版本,如:1.20 Legacy versions 旧的稳定版,一般为偶数版本,如:1.18 Nginx安装可以使用yum或源码安装但是推荐使用源码编译安装yum的版本比较旧 编译安装可以更方便自定义相关路径 使用源码编译可以自定义相关功能更方便业务的上的使用 3.1.2 Nginx 编译安装 编译器介绍 源码安装需要提前准备标准的编译器GCC的全称是GNU Compiler collection其有GNU开发并以 GPL即LGPL许可是自由的类UNIX即苹果电脑Mac OS X操作系统的标准编译器因为GCC原本只能处理C语 言所以原名为GNU C语言编译器后来得到快速发展可以处理C,Fortranpascalobjective C java以及Ada等其他语言此外还需要Automake工具以完成自动创建Makefile的工作Nginx的一些模块需要依赖第三方库比如: pcre支持rewritezlib支持gzip模块和openssl支持ssl模块 等。 编译安装 Nginx 官方源码包下载地址https://nginx.org/en/download.html编译安装示例: [rootwebserver ~]# ls
anaconda-ks.cfg nginx-1.24.0.tar.gz nginx-1.26.1.tar.gz
#这里先下载nginx-1.24.0.tar.gz为后面平滑升级示例做准备[rootwebserver ~]# tar zxf nginx-1.24.0.tar.gz #解压
[rootwebserver ~]# cd nginx-1.24.0/
[rootwebserver nginx-1.24.0]# useradd -s /sbin/nologin -M nginx #创建用户
[rootwebserver nginx-1.24.0]# dnf install gcc pcre-devel zlib-devel openssl-devel -y #下载源码编译所需前置[rootwebserver nginx-1.24.0]# ./configure --prefix/usr/local/nginx \
--usernginx \ # 指定nginx运行用户
--groupnginx \ # 指定nginx运行组
--with-http_ssl_module \ # 支持https://
--with-http_v2_module \ # 支持http版本2
--with-http_realip_module \ # 支持ip透传
--with-http_stub_status_module \ # 支持状态页面
--with-http_gzip_static_module \ # 支持压缩
--with-pcre \ # 支持正则
--with-stream \ # 支持tcp反向代理
--with-stream_ssl_module \ # 支持tcp的ssl加密
--with-stream_realip_module # 支持tcp的透传ip[rootwebserver nginx-1.24.0]# make make install #静候编译完成[rootwebserver nginx-1.24.0]# ls /usr/local/nginx/
conf html logs sbinconf保存nginx所有的配置文件其中nginx.conf是nginx服务器的最核心最主要的配置文件其他
的.conf则是用来配置nginx相关的功能的例如fastcgi功能使用的是fastcgi.conf和fastcgi_params
两个文件配置文件一般都有一个样板配置文件是以.default为后缀使用时可将其复制并将default后缀
去掉即可。html目录中保存了nginx服务器的web文件但是可以更改为其他目录保存web文件,另外还有一个50x的web
文件是默认的错误页面提示页面。logs用来保存nginx服务器的访问日志错误日志等日志logs目录可以放在其他路径比
如/var/logs/nginx里面。sbin保存nginx二进制启动脚本可以接受不同的参数以实现不同的功能。 3.1.3 设置环境变量和启动文件 ###设置环境变量以便后续直接使用nginx指令
[rootwebserver nginx-1.24.0]# vim ~/.bash_profile
export PATH$PATH:/usr/local/nginx/sbin[rootwebserver nginx-1.24.0]# source ~/.bash_profile
[rootwebserver nginx-1.24.0]# nginx -V #查看版本信息
nginx version: nginx/1.24.0
built by gcc 11.4.1 20230605 (Red Hat 11.4.1-2) (GCC)
built with OpenSSL 3.0.7 1 Nov 2022
TLS SNI support enabled
configure arguments: --prefix/usr/local/nginx --usernginx --groupnginx --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###设置启动脚本
[rootwebserver nginx-1.24.0]# vim /lib/systemd/system/nginx.service
[Unit]
DescriptionThe NGINX HTTP and reverse proxy server
Aftersyslog.target network-online.target remote-fs.target nss-lookup.target[Service]
Typeforking
PIDFile/usr/local/nginx/logs/nginx.pid
ExecStartPre/usr/local/nginx/sbin/nginx -t
ExecStart/usr/local/nginx/sbin/nginx
ExecReload/bin/kill -s HUP $MAINPID
ExecStop/bin/kill -s QUIT $MAINPID
PrivateTmptrue[Install]
WantedBymulti-user.target
[rootwebserver nginx-1.24.0]# systemctl daemon-reload
[rootwebserver nginx-1.24.0]# systemctl start nginx.service 3.1.4 平滑升级和回滚
有时候我们需要对Nginx版本进行升级以满足对其功能的需求例如添加新模块需要新功能而此时Nginx又在跑着业务无法停掉这时我们就可能选择平滑升级将旧Nginx二进制文件换成新Nginx程序文件注意先备份) 向master进程发送USR2信号 master进程修改pid文件名加上后缀.oldbin,成为nginx.pid.oldbin master进程用新Nginx文件启动新master进程成为旧master的子进程,系统中将有新旧两个Nginx主进程共同提供Web服务,当前新的请求仍然由旧Nginx的worker进程进行处理,将新生成的master进程的PID存放至新生成的pid文件nginx.pid 向旧的Nginx服务进程发送WINCH信号使旧的Nginx worker进程平滑停止 向旧master进程发送QUIT信号关闭老master并删除Nginx.pid.oldbin文件 如果发现升级有问题,可以回滚∶向老master发送HUP向新master发送QUIT 示例
###平滑升级
[rootwebserver nginx-1.24.0]# cd ~
[rootwebserver ~]# ls
anaconda-ks.cfg nginx-1.24.0 nginx-1.24.0.tar.gz nginx-1.26.1.tar.gz
[rootwebserver ~]# tar zxf nginx-1.26.1.tar.gz
[rootwebserver ~]# cd nginx-1.26.1/
[rootwebserver nginx-1.26.1]# ./configure --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
[rootwebserver nginx-1.26.1]# make[rootwebserver nginx-1.26.1]# ll objs/nginx /usr/local/nginx/sbin/nginx
-rwxr-xr-x 1 root root 5752872 Aug 11 16:44 objs/nginx
-rwxr-xr-x 1 root root 5678264 Aug 11 16:21 /usr/local/nginx/sbin/nginx#复制旧的nginx
[rootwebserver nginx-1.26.1]# cd /usr/local/nginx/sbin/
[rootwebserver sbin]# cp nginx nginx.24
[rootwebserver sbin]# ls
nginx nginx.24
[rootwebserver sbin]# cp -f ~/nginx-1.26.1/objs/nginx /usr/local/nginx/sbin #新的取代旧的[rootwebserver sbin]# ps aux|grep nginx
root 34849 0.0 0.0 9864 928 ? Ss 16:36 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx 34850 0.0 0.2 13760 4708 ? S 16:36 0:00 nginx: worker process
root 37919 0.0 0.1 6408 2176 pts/0 S 16:51 0:00 grep --colorauto nginx
[rootwebserver sbin]# kill -USR2 34849
[rootwebserver sbin]# ps aux|grep nginx
root 34849 0.0 0.1 9864 2528 ? Ss 16:36 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx 34850 0.0 0.2 13760 4708 ? S 16:36 0:00 nginx: worker process
root 37920 0.0 0.3 9872 6092 ? S 16:52 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nobody 37921 0.0 0.2 13768 4628 ? S 16:52 0:00 nginx: worker process
root 37923 0.0 0.1 6408 2164 pts/0 S 16:52 0:00 grep --colorauto nginx#USR2平滑升级可执行程序,将存储有旧版本主进程PID的文件重命名为nginx.pid.oldbin并启动新的nginx
#此时两个master的进程都在运行,只是旧的master不在监听,由新的master监听80
#此时Nginx开启一个新的master进程这个master进程会生成新的worker进程这就是升级后的Nginx进程,此时老的进程不会自动退出但是当接收到新的请求不作处理而是交给新的进程处理。#回收旧版本
rootwebserver sbin]# kill -WINCH 34849
[rootwebserver sbin]# ps aux|grep nginx
root 34849 0.0 0.1 9864 2528 ? Ss 16:36 0:00 nginx: master process /usr/local/nginx/sbin/nginx
root 37920 0.0 0.3 9872 6092 ? S 16:52 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nobody 37921 0.0 0.2 13768 4628 ? S 16:52 0:00 nginx: worker process
root 37932 0.0 0.1 6408 2184 pts/0 S 16:54 0:00 grep --colorauto nginx#测试
[rootwebserver sbin]# curl -I localhost
...
Server: nginx/1.26.1
...###回滚
[rootwebserver sbin]# cp nginx nginx.26 #此时的nginx是新版本的
[rootwebserver sbin]# ls
nginx nginx.24 nginx.26
[rootwebserver sbin]# mv nginx.24 nginx
mv: overwrite nginx? y
[rootwebserver sbin]# kill -HUP 34849
[rootwebserver sbin]# kill -WINCH 37920
[rootwebserver sbin]# ps aux|grep nginx
root 34849 0.0 0.1 9864 2528 ? Ss 16:36 0:00 nginx: master process /usr/local/nginx/sbin/nginx
root 37920 0.0 0.3 9872 6092 ? S 16:52 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx 37958 0.0 0.2 13760 4708 ? S 17:00 0:00 nginx: worker process
root 37977 0.0 0.1 6408 2180 pts/0 S 17:01 0:00 grep --colorauto nginx[rootwebserver sbin]# curl -I localhost
...
Server: nginx/1.24.0
...
注意后面的实验使用的是新装的nginx1.26是将/usr/local/nginx删掉后重新编译的
3.2 高并发配置
[rootwebserver ~]# cd /usr/local/nginx
[rootwebserver nginx]# vim conf/nginx.conf
...
worker_processes 4;
worker_cpu_affinity 0001 0010 0100 1000;
worker_rlimit_nofile 100000;
...
events {
...worker_connections 100000;use epoll;
...
}[rootwebserver nginx]# vim /etc/security/limits.conf
* - nproc 100000
* - nofile 100000
[rootwebserver nginx]# ulimit -n 100000#测试
[rootwebserver nginx]# dnf install httpd-tools-2.4.57-5.el9.x86_64
[rootwebserver nginx]# echo webservera html/index.html
[rootwebserver nginx]# systemctl restart nginx
[rootwebserver nginx]# ab -c 5000 -n 10000 http://172.25.254.10/
...
Complete requests: 10000
Failed requests: 0
...3.3 建立首个web站点
#配置网站
[rootwebserver nginx]# vim conf/nginx.conf
http{
...
include/apps/nginx/conf/conf.d/*.conf; #在http里的最后添加不然会导致前面的指令无法生效
}[rootwebserver nginx]# mkdir /usr/local/nginx/conf.d
server {listen 80;server_name www.timinglee.org;root /web/html;index index.html;
}#创建访问的文件
[rootwebserver nginx]# mkdir /web/html -p
[rootwebserver nginx]# echo web_html /web/html/index.html#添加域名解析
[rootwebserver nginx]# vim /etc/hosts
172.25.254.10 webserver.timinglee.org www.timinglee.org#测试
[rootwebserver nginx]# curl www.timinglee.org
webservera
补充 3.4 root与alias
root指定web的家目录在定义location的时候文件的绝对路径等于 rootlocatialias定义路径别名会把访问的路径重新定义到其指定的路径,文档映射的另一种机制;仅能用于location上下文,此指令使用较少#
[rootwebserver nginx]# vim conf.d/vhosts.conf
server {listen 80;server_name www.timinglee.org;root /web/html;index index.html;location /root {root /web/;}location /alias {alias /web/root;}
}[rootwebserver nginx]# nginx -s reload#测试
[rootwebserver nginx]# mkdir /web/root/
[rootwebserver nginx]# echo 无论这么访问都是root /web/root/index.html
[rootwebserver nginx]# curl www.timinglee.org/root/
无论这么访问都是root
[rootwebserver nginx]# curl www.timinglee.org/alias/
无论这么访问都是root3.5 用户认证访问 [rootwebserver nginx]# htpasswd -cmb conf/.htpasswd admin lee
Adding password for user admin
[rootwebserver nginx]# htpasswd -mb conf/.htpasswd lee lee
Adding password for user lee
[rootwebserver nginx]# mkdir /web/auth/
[rootwebserver nginx]# echo login /web/auth/index.html
[rootwebserver nginx]# vim conf.d/vhosts.conf
server {listen 80;server_name www.timinglee.org;root /web/html;index index.html;location /auth {root /web/auth_basic login password;auth_basic_user_file /usr/local/nginx/conf/.htpasswd;}
}
[rootwebserver nginx]# nginx -s reload
[rootwebserver nginx]# curl www.timinglee.org/auth/ -u lee:lee
login3.6 自定义错误页面 [rootwebserver nginx]# vim conf.d/vhosts.conf
server {listen 80;server_name www.timinglee.org;root /web/html;index index.html;error_page 500 502 503 504 /error.html;location /error.html {root /web/error/;}
}
[rootwebserver nginx]# nginx -s reload
[rootwebserver nginx]# mkdir /web/error
[rootwebserver nginx]# echo errorlll /web/error/error.html[rootwebserver nginx]# curl www.timinglee.org/aa
errorlll3.7 自定义日志 [rootwebserver nginx]# vim conf.d/vhosts.conf
server {listen 80;server_name www.timinglee.org;root /web/html;index index.html;access_log /var/log/nginx/access.log;error_log /var/log/nginx/error.log;
}
[rootwebserver nginx]# nginx -s reload[rootwebserver nginx]# mkdir /var/log/nginx -p
[rootwebserver nginx]# touch /var/log/nginx/access.log
[rootwebserver nginx]# touch /var/log/nginx/error.log#测试
[rootwebserver nginx]# curl 172.25.254.10
webservera
[rootwebserver nginx]# curl www.timinglee.org
...
[rootwebserver nginx]# cat /var/log/nginx/error.log
2025/08/11 19:13:22 [error] 41686#0: *12245 directory index of /web/ is forbidden, client: 172.25.254.10, server: www.timinglee.org, request: GET / HTTP/1.1, host: www.timinglee.org
[rootwebserver nginx]# cat /var/log/nginx/access.log
172.25.254.10 - - [11/Aug/2025:19:13:22 0800] GET / HTTP/1.1 403 153 - curl/7.76.13.8 文件检测 [rootwebserver nginx]# vim conf.d/vhosts.conf
server {listen 80;server_name www.timinglee.org;root /web/html;index index.html;error_page 404 /web/error/error.html try_files $uri.html $uri.html $uri/index.html /web/default.html;location /error {root /web/;}
} [rootwebserver nginx]# nginx -s reload
[rootwebserver nginx]# curl www.timinglee.org/a/
defautl3.9 长连接配置 [rootwebserver nginx]# vim conf.d/vhosts.conf
server {listen 80;server_name www.timinglee.org;root /web/html;index index.html;keepalive_timeout 65; #65秒后自动断开#连接请求3次后断开
#开启长连接后返回客户端的会话保持时间为60s单次长连接累计请求达到指定次数请求或65秒就会被断
开第二个数字60为发送给客户端应答报文头部中显示的超时时间设置为60s如不设置客户端将不显示超时时
间。keepalive_requests 3;
#浏览器收到的服务器返回的报文
#如果设置为0表示关闭会话保持功能将如下显示
#Connection:close 浏览器收到的服务器返回的报文error_log /var/log/nginx/error.log;
}
[rootwebserver nginx]# dnf install telnet -y
[rootwebserver nginx]# telnet 172.25.254.10 80
Trying 172.25.254.10...
Connected to 172.25.254.10.
Escape character is ^].
GET / HTTP/1.1
Host: www.timinglee.orgHTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Mon, 11 Aug 2025 13:27:13 GMT
Content-Type: text/html
Content-Length: 9
Last-Modified: Mon, 11 Aug 2025 10:31:31 GMT
Connection: keep-alive
ETag: 6899c683-9
Accept-Ranges: bytesweb_htmlGET / HTTP/1.1
Host: www.timinglee.orgHTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Mon, 11 Aug 2025 13:27:38 GMT
Content-Type: text/html
Content-Length: 9
Last-Modified: Mon, 11 Aug 2025 10:31:31 GMT
Connection: keep-alive
ETag: 6899c683-9
Accept-Ranges: bytesweb_html
GET / HTTP/1.1
Host: www.timinglee.orgHTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Mon, 11 Aug 2025 13:27:46 GMT
Content-Type: text/html
Content-Length: 9
Last-Modified: Mon, 11 Aug 2025 10:31:31 GMT
Connection: close
ETag: 6899c683-9
Accept-Ranges: bytesweb_html
Connection closed by foreign host.
[rootwebserver nginx]# 3.10 下载服务器部署 #创建下载文件
[rootwebserver nginx]# mkdir /web/download
[rootwebserver nginx]# dd if/dev/zero of/web/download/lee bs1M count500
5000 records in
5000 records out
524288000 bytes (524 MB, 500 MiB) copied, 3.28797 s, 159 MB/s[rootwebserver nginx]# vim conf.d/vhosts.conf
server {listen 80;server_name www.timinglee.org;root /web/html;index index.html;error_log /var/log/nginx/error.log;location /download {root /web/;autoindex on; #自动索引功能autoindex_exact_size on; #计算文件确切大小单位bytes此为默认值,off只显示大概大小单位kb、mb、gbautoindex_localtime on; #on表示显示本机时间而非GMT(格林威治)时间,默为为off显示GMT时间limit_rate 1024k; #限速,默认不限速}
}[rootwebserver nginx]# nginx -s reload[rootwebserver nginx]# curl www.timinglee.org/download/
html
headtitleIndex of /download//title/head
body
h1Index of /download//h1hrprea href../..//a
a hrefleelee/a 11-Aug-2025 21:37 524288000
/prehr/body
/html3.11 nginx状态页 基于nginx 模块 ngx_http_stub_status_module 实现 在编译安装nginx的时候需要添加编译参数 --with-http_stub_status_module 否则配置完成之后监测会是提示法错误 注意: 状态页显示的是整个服务器的状态,而非虚拟主机的状态[rootwebserver nginx]# vim conf.d/vhosts.conf
server {listen 80;server_name www.timinglee.org;root /web/html;index index.html;error_log /var/log/nginx/error.log;location /status {stub_status;auth_basic status page; #开启状态页auth_basic_user_file /usr/local/nginx/conf/.htpasswd; #用户认证文件}
}
[rootwebserver nginx]# nginx -s reload3.12 网页压缩功能 [rootwebserver nginx]# vim conf.d/vhosts.conf
server {listen 80;server_name www.timinglee.org;root /web/html;index index.html;error_log /var/log/nginx/error.log;
#启用或禁用gzip压缩默认关闭gzip on;
#压缩比由低到高从1到9默认为1值越高压缩后文件越小但是消耗cpu比较高。基本设定未4或者5gzip_comp_level 4;
#禁用IE6 gzip功能早期的IE6之前的版本不支持压缩gzip_disable MSIE [1-6]\.;
#gzip压缩的最小文件小于设置值的文件将不会压缩gzip_min_length 1k;
#启用压缩功能时协议的最小版本默认HTTP/1.1gzip_http_version 1.1;
#指定Nginx服务需要向服务器申请的缓存空间的个数和大小,平台不同,默认:32 4k或者16 8k;gzip_buffers 16 8k;
#指明仅对哪些类型的资源执行压缩操作;默认为gzip_types text/html不用显示指定否则出错
# gzip_types ...;
#如果启用压缩是否在响应报文首部插入“Vary: Accept-Encoding”,一般建议打开gzip_vary on;
#预压缩即直接从磁盘找到对应文件的gz后缀的式的压缩文件返回给用户无需消耗服务器CPU
#注意: 来自于ngx_http_gzip_static_module模块gzip_static on;
}
[rootwebserver nginx]# nginx -s reloadcp /usr/local/nginx/logs/access.log /web/html/data.html
[rootwebserver nginx]# curl --head --compressed 172.25.254.10/data.html
HTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Mon, 11 Aug 2025 14:15:49 GMT
Content-Type: text/html
Last-Modified: Mon, 11 Aug 2025 14:13:09 GMT
Connection: keep-alive
Vary: Accept-Encoding
ETag: W/6899fa75-4bc2d0
Content-Encoding: gzip3.13 Nginx 变量使用 nginx的变量可以在配置文件中引用作为功能判断或者日志等场景使用 变量可以分为内置变量和自定义变量 内置变量是由nginx模块自带通过变量可以获取到众多的与客户端访问相关的值。 [rootwebserver nginx]# cd ~
[rootwebserver ~]# ls
anaconda-ks.cfg nginx-1.24.0 nginx-1.26.1
echo-nginx-module-0.63.tar.gz nginx-1.24.0.tar.gz nginx-1.26.1.tar.gz
[rootwebserver ~]# tar zxf echo-nginx-module-0.63.tar.gz
[rootwebserver ~]# rm -rf nginx-1.26.1[rootwebserver ~]# nginx -V
nginx version: nginx/1.26.1
built by gcc 11.4.1 20230605 (Red Hat 11.4.1-2) (GCC)
built with OpenSSL 3.0.7 1 Nov 2022
TLS SNI support enabled
configure arguments: --prefix/usr/local/nginx --usernginx --groupnginx --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[rootwebserver ~]# tar zxf nginx-1.26.1.tar.gz
[rootwebserver ~]# cd nginx-1.26.1/#在之前的./configure里加上 --add-module/root/echo-nginx-module-0.63
[rootwebserver nginx-1.26.1]# ./configure --prefix/usr/local/nginx --usernginx --groupnginx --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/root/echo-nginx-module-0.63[rootwebserver nginx-1.26.1]# cd objs/
[rootwebserver objs]# cp -p nginx /usr/local/nginx/sbin/nginx
[rootwebserver objs]# cp /usr/local/nginx/conf/nginx.conf /mnt
[rootwebserver objs]# cp -rp /usr/local/nginx/conf.d /mnt
[rootwebserver objs]# rm -rf /usr/local/nginx/
[rootwebserver objs]# cd ..
[rootwebserver nginx-1.26.1]# make install[rootwebserver nginx-1.26.1]# cp /mnt/nginx.conf /usr/local/nginx/conf/nginx.conf
cp: overwrite /usr/local/nginx/conf/nginx.conf? y
[rootwebserver nginx-1.26.1]# cp -r /mnt/conf.d/ /usr/local/nginx/[rootwebserver nginx]# vim conf.d/vhosts.conf
server {listen 80;server_name www.timinglee.org;root /web/html;index index.html;error_log /var/log/nginx/error.log;location /test {default_type text/html;echo $remote_addr;echo $args;echo $document_root;echo $document_uri;echo $host;echo $http_user_agent;}
}[rootwebserver nginx]# systemctl restart nginx.service
[rootwebserver nginx]# nginx -s reload
[rootwebserver nginx]# curl www.timinglee.org/test
172.25.254.10/web/html
/test
www.timinglee.org
curl/7.76.1#官方文档 http://nginx.org/en/docs/varindex.html
#常用内置变量
$remote_addr;
#存放了客户端的地址注意是客户端的公网IP$args;
#变量中存放了URL中的所有参数
#例如:https://search.jd.com/Search?keyword手机encutf-8
#返回结果为: keyword手机encutf-8$is_args
#如果有参数为? 否则为空$document_root;
#保存了针对当前资源的请求的系统根目录,例如:/webdata/nginx/timinglee.org/lee。$document_uri;
#保存了当前请求中不包含参数的URI注意是不包含请求的指令
#比如:http://lee.timinglee.org/var?\id11111会被定义为/var
#返回结果为:/var$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请求生成的文件绝对路径
#如:webdata/nginx/timinglee.org/lee/var/index.html$request_uri;
#包含请求参数的原始URI不包含主机名相当于:$document_uri?$args,
#例如/main/index.do?id20190221partnersearch$scheme;
#请求的协议例如:httphttps,ftp等$server_protocol;
#保存了客户端请求资源使用的协议的版本例如:HTTP/1.0HTTP/1.1HTTP/2.0等$server_addr;
#保存了服务器的IP地址$server_name;
#虚拟主机的主机名$server_port;
#虚拟主机的端口号$http_user_agent;
#客户端浏览器的详细信息$http_cookie;
#客户端的所有cookie信息$cookie_name
#name为任意请求报文首部字部cookie的key名$http_name
#name为任意请求报文首部字段,表示记录请求报文的首部字段name的对应的首部字段名需要为小写如果有
横线需要替换为下划线
#示例:
echo $http_user_agent;
echo $http_host;$sent_http_name
#name为响应报文的首部字段name的对应的首部字段名需要为小写如果有横线需要替换为下划线,此变量有
问题
echo $sent_http_server;$arg_name
#此变量存放了URL中的指定参数name为请求url中指定的参数
echo $arg_id;
3.14 rewrite模块
Nginx服务器利用 ngx_http_rewrite_module 模块解析和处理rewrite请求 此功能依靠 PCRE(perl compatible regular expression)因此编译之前要安装PCRE库 rewrite是nginx服务器的重要功能之一用于实现URL的重写URL的重写是非常有用的功能 比如它可以在我们改变网站结构之后不需要客户端修改原来的书签也无需其他网站修改我们的链接就可以设置为访问 另外还可以在一定程度上提高网站的安全性
官方文档: https://nginx.org/en/docs/http/ngx_http_rewrite_module.html3.14.1 if指令 用于条件匹配判断并根据条件判断结果选择不同的Nginx配置可以配置在server或location块中进行配置Nginx的if语法仅能使用if做单次判断不支持使用if else或者if elif这样的多重判断用法如下 3.14.2 set 指令 指定key并给其定义一个变量变量可以调用Nginx内置变量赋值给key 另外set定义格式为set $key valuevalue可以是text, variables和两者的组合。 3.14.3 break 指令 用于中断当前相同作用域(location)中的其他Nginx配置 与该指令处于同一作用域的Nginx配置中位于它前面的配置生效 位于后面的 ngx_http_rewrite_module 模块中指令就不再执行 Nginx服务器在根据配置处理请求的过程中遇到该指令的时候回到上一层作用域继续向下读取配置该指令可以在server块和locationif块中使用 注意: 如果break指令在location块中后续指令还会继续执行,只是不执行 ngx_http_rewrite_module 模块的指令,其它指令还会执行3.14.4 return 指令
return用于完成对请求的处理并直接向客户端返回响应状态码比如:可以指定重定向URL(对于特殊重定向状态码301/302等) 或者是指定提示文本内容(对于特殊状态码403/500等)处于此指令后的所有配置都将不被执行return可以在server、if 和 location块进行配置3.14.5 rewrite指令
通过正则表达式的匹配来改变URI可以同时存在一个或多个指令按照顺序依次对URI进行匹配rewrite主要是针对用户请求的URL或者是URI做具体处理语法格式rewrite regex replacement [flag]; rewrite将用户请求的URI基于regex所描述的模式进行检查匹配到时将其替换为表达式指定的新的URI 注意如果在同一级配置块中存在多个rewrite规则那么会自下而下逐个检查;被某条件规则替换完成 后会重新一轮的替换检查隐含有循环机制,但不超过10次;如果超过提示500响应码[flag]所表示的 标志位用于控制此循环机制 如果替换后的URL是以http://或https://开头则替换结果会直接以重定向返回给客户端, 即永久重定向301 rewrite flag 使用介绍利用nginx的rewrite的指令可以实现url的重新跳转rewrite有四种不同的flag分别是redirect(临时重定向302)、permanent(永久重定向301)、break和last。其中前两种是跳转型的flag后两种是代理型 跳转型指由客户端浏览器重新对新地址进行请求 代理型是在WEB服务器内部实现跳转 rewrite格式rewrite regex replacement [flag] [rootwebserver nginx]# vim conf.d/vhosts.conf
server {listen 80;server_name www.timinglee.org;root /web/html;index index.html;error_log /var/log/nginx/error.log;location /test {root /web/;rewrite ^/test http://www.timinglee.org;}location /break/ {rewrite ^/break/(.*) /test1/$1 break;rewrite ^/test1/(.*) /test2/$1 ;}location /last/ {rewrite ^/last/(.*) /test1/$1 last;rewrite ^/test1/(.*) /test2/$1 ;}location /test1 {return 666 test1;}location /test2 {return 22 test2;}
}
[rootwebserver nginx]# nginx -s reload
[rootwebserver nginx]# mkdir /web/html/{test1,test2,break,last} -p
[rootwebserver nginx]# echo this is test1 /web/html/test1/index.html
[rootwebserver nginx]# echo this is test2 /web/html/test2/index.html[rootwebserver nginx]# curl -L www.timinglee.org/test
web_html
[rootwebserver nginx]# curl -L www.timinglee.org/break/index.html
this is test1
[rootwebserver nginx]# curl -L www.timinglee.org/last/index.html
test1[rootwebserver nginx]#
3.14.6 rewrite实现全站加密
案例基于通信安全考虑公司网站要求全站 https因此要求将在不影响用户请求的情况下将http请求全部自动跳转至 https另外也可以实现部分 location 跳转[rootwebserver nginx]# mkdir /usr/local/nginx/certs
[rootwebserver nginx]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /usr/local/nginx/certs/timinglee.org.key -x509 -days 365 -out
/usr/local/nginx/certs/timinglee.org.crt[rootwebserver nginx]# vim conf.d/vhosts.conf
server {listen 80;server_name www.timinglee.org;root /web/html;index index.html;error_log /var/log/nginx/error.log;ssl_certificate /usr/local/nginx/certs/timinglee.org.crt;ssl_certificate_key /usr/local/nginx/certs/timinglee.org.key;ssl_session_cache shared:sslcache:1m;ssl_session_timeout 5m;location / {if ($scheme http ){rewrite / https://$host;}}
} [rootwebserver nginx]# nginx -s reload[rootwebserver nginx]# curl -I http://www.timinglee.org
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.26.1
Date: Mon, 11 Aug 2025 15:37:58 GMT
Content-Type: text/html
Content-Length: 145
Connection: keep-alive
Location: https://www.timinglee.org3.14.7 不存在页面重定向 [rootwebserver nginx]# vim conf.d/vhosts.conf
server {listen 80;server_name www.timinglee.org;root /web/html;index index.html;error_log /var/log/nginx/error.log;if (!-e $request_filename) {rewrite .* http://www.timinglee.org}
}
[rootwebserver nginx]# nginx -s reload[rootwebserver nginx]# curl -L www.timinglee.org/asdaw/
web_html3.15 防盗链
防盗链基于客户端携带的referer实现referer是记录打开一个页面之前记录是从哪个页面跳转过来的标 记信息如果别人只链接了自己网站图片或某个单独的资源而不是打开了网站的整个页面这就是盗链referer就是之前的那个网站域名正常的referer信息有以下几种防盗链的实现
#RS1模拟盗链客户端
[rootRS1 ~]# dnf install httpd
[rootRS1 ~]# vim /var/www/html/index.html
html
head
meta http-equivContent-Type contenttext/html;charsetutf-8
title盗链/title
/head
body
img srchttp://www.timinglee.org/images/lee.png
h1 stylecolor:red欢迎大家/h1
pa hrefhttp://www.timinglee.org狂点老李/a出门见喜/p
/body
/html[rootRS1 ~]# vim /etc/hosts
172.25.254.10 www.timinglee.org
[rootRS1 ~]# systemctl start httpd#准备好照片
[rootwebserver nginx]# mkdir /web/html/image
[rootwebserver nginx]# cp ~/test.png /web/html/image/实现防盗链
#webserver
[rootwebserver nginx]# vim conf.d/vhosts.conf
server {listen 80;server_name www.timinglee.org;root /web/html;index index.html;error_log /var/log/nginx/error.log;location / {valid_referers none blocked server_names *.timinglee.org ~/.baidu/.;if ($invalid_referer){return 404;}}
}
[rootwebserver nginx]# nginx -s reload3.16 反向代理实现动静分离 反向代理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协议转发至指定服务器处理#官方文档https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
proxy_pass; #用来设置将客户端请求转发给的后端服务器的主机#可以是主机名(将转发至后端服务做为主机头首部)、IP地址端口的方式#也可以代理到预先设置的主机群组需要模块ngx_http_upstream_module支持
#示例:
proxy_pass http://172.25.254.30:8080; #8080后面无uri,即无 / 符号,#需要将location后面url 附加到proxy_pass指定的url后面#此行为类似于root#proxy_pass指定的uri不带斜线将访问的/web#等于访问后端服务器
proxy_pass http://172.25.254.40:8080/; #8080后面有uri,即有 / 符号#相当于置换,即访问/web时实际返回proxy_pass后面uri内容#此行为类似于alias#proxy_pass指定的uri带斜线#等于访问后端服务器的#http://172.25.254.40:8080/index.html#内容返回给客户端
#如果location定义其uri时使用了正则表达式模式(包括~,~*,但不包括^~)则proxy_pass之后必须不能
使用uri
#即不能有/ ,用户请求时传递的uri将直接附加至后端服proxy_hide_header field; #用于nginx作为反向代理的时候#在返回给客户端http响应时#隐藏后端服务器相应头部的信息#可以设置在http,server或location块务器之后proxy_pass_header field; #透传#默认nginx在响应报文中不传递后端服务器的首部字段Date, Server, X-Pad, X-Accel等参数#如果要传递的话则要使用 proxy_pass_header field声明将后端服务器返回的值传递给客户端#field 首部字段大小不敏感proxy_pass_request_body on | off;#是否向后端服务器发送HTTP实体部分,可以设置在http,server或location块默认即为开启proxy_pass_request_headers on | off;#是否将客户端的请求头部转发给后端服务器可以设置在http,server或location块默认即为开启proxy_set_header;#可更改或添加客户端的请求头部信息内容并转发至后端服务器比如在后端服务器想要获取客户端的真实IP的时候就要更改每一个报文的头部proxy_connect_timeout time;#配置nginx服务器与后端服务器尝试建立连接的超时时间默认为60秒用法如下proxy_connect_timeout 6s;#60s为自定义nginx与后端服务器建立连接的超时时间,超时会返回客户端504响应码proxy_read_timeout time;#配置nginx服务器向后端服务器或服务器组发起read请求后等待的超时时间默认60sproxy_send_timeout time;#配置nginx项后端服务器或服务器组发起write请求后等待的超时 时间默认60sproxy_http_version 1.0;#用于设置nginx提供代理服务的HTTP协议的版本默认http 1.0proxy_ignore_client_abort off;#当客户端网络中断请求时nginx服务器中断其对后端服务器的请求。即如果此项设置为on开启则服务器、会忽略客户端中断并一直等着代理服务执行返回如果设置为off则客户端中断后Nginx也会中断客户端请求并立即记录499日志默认为off。 逻辑调用关系: 访问逻辑图: 同构代理用户不需要其他程序的参与直接通过http协议或者tcp协议访问后端服务器 异构代理用户访问的资源时需要经过处理后才能返回的比如phppython等等这种访问资源需要经过处理才能被访问示例#RS1
[rootRS1 ~]# echo 172.25.254.100 /var/www/html/index.html#RS2
[rootRS2 ~]# systemctl restart httpd
[rootRS2 ~]# mkdir /var/www/html/php/
[rootRS2 ~]# vim /var/www/html/php/index.php
?phpphpinfo ();
?#webserver
[rootwebserver nginx]# vim conf.d/vhosts.conf
server {listen 80;server_name www.timinglee.org;root /web/html;error_log /var/log/nginx/error.log;location / {proxy_pass http://172.25.254.100:80;}location ~ \.(php|jpg|gif) {proxy_pass http://172.25.254.200:80;}
}
[rootwebserver nginx]# nginx -s reload3.17 反向代理缓存功能
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;#定义对特定响应码的响应内容的缓存
示例:
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;时长定义在http{...}中proxy_cache_path;
#定义可用于proxy功能的缓存;Context:http
proxy_cache_path path [levelslevels] [use_temp_pathon|off]
keys_zonezone_name:size [inactivetime] [max_sizesize] [manager_filesnumber]
[manager_sleeptime] [manager_thresholdtime] [loader_filesnumber]
[loader_sleeptime] [loader_thresholdtime] [purgeron|off]
[purger_filesnumber] [purger_sleeptime] [purger_thresholdtime];proxy_cache_path /var/cache/nginx/proxy_cache #定义缓存保存路径proxy_cache会自动创建levels1:2:2 #定义缓存目录结构层次#1:2:2可以生成keys_zoneproxycache:20m #指内存中缓存的大小主要用于存放key和metadata
如使用次数#一般1M可存放8000个左右的keyinactive120s #缓存有效时间max_size10g; #最大磁盘占用空间磁盘存入文件内容的缓存空间最大值#调用缓存功能需要定义在相应的配置段如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方法总是被缓存
示例:
#webserver
[rootwebserver nginx]# vim conf.d/vhosts.conf
server {listen 80;server_name www.timinglee.org;root /web/html;error_log /var/log/nginx/error.log;location / {proxy_pass http://www.lee.org;proxy_cache proxycache;proxy_cache_key $request_uri;proxy_cache_valid 200 302 10m;proxy_cache_valid any 1m;}location ~ \.(php|jpg|gif)$ {proxy_pass http://172.25.254.200:80;}
}
[rootwebserver nginx]# vim conf/nginx.conf
http{
...proxy_cache_path /usr/local/nginx/cache levels1:2:2 keys_zoneproxycache:20m inactive120s max_size10g;
...
}#加缓存之前
[rootRS2 ~]# ab -c 500 -n 10000 http://www.timinglee.org/index.html
Time per request: 1846.322 [ms] (mean)#加缓存之后
[rootRS2 ~]# ab -c 500 -n 10000 http://www.timinglee.org/index.html
Time per request: 230.727 [ms] (mean)
3.18 四层负载
bind的四层负载
#RS1 和 RS2
[rootRS1 ~]# dnf install bind -y
[rootRS1 ~]# vim /etc/named.conf
options {
// listen-on port 53 { 127.0.0.1; };
// listen-on-v6 port 53 { ::1; };
...
// allow-query { localhost; };
...dnssec-validation no;}
[rootRS1 ~]# cd /var/named
[rootRS1 named]# cp -p named.localhost timinglee.org.zone
[rootRS1 named]# vim timinglee.org.zone #RS2下面的ip是200
$TTL 1DIN SOA dns.timinglee.org. root.timinglee.org. (0 ; serial1D ; refresh1H ; retry1W ; expire3H ) ; minimumNS dns.timinglee.org.
dns A 172.25.254.100
[rootRS1 named]# vim /etc/named.rfc1912.zones
...
zone timinglee.org IN {type master;file timinglee.org.zone;allow-update { none; };
};
...
[rootRS1 named]# systemctl restart named#webserver
[rootwebserver nginx]# mkdir tcp.d
[rootwebserver nginx]# vim tcp.d/dns.conf
[rootwebserver nginx]# vim conf/nginx.conf
include /usr/local/nginx/tcp.d/*.conf ; #不能写在http语句块中
[rootwebserver nginx]# vim tcp.d/dns.conf
stream {upstream dns {server 172.25.254.100:53 max_fails3 fail_timeout5;server 172.25.254.200:53 max_fails3 fail_timeout5;}server {listen 53 udp;proxy_pass dns;}
}
[rootwebserver nginx]# nginx -s reload
测试: mariadb的四层负载
#RS1和RS2
[rootRS1 named]# vim /etc/my.cnf.d/mariadb-server.cnf
...
[mysqld]
server-id 100 #RS2的是200
...
[rootRS1 named]# systemctl start mariadb.service
[rootRS1 named]# mysql -e create user lee% identified by lee;
[rootRS1 named]# mysql -e grant select on *.* to lee%;[rootwebserver nginx]# vim tcp.d/dns.conf #stream只能有一个,写在别的文件也不行
stream {upstream mariadb {server 172.25.254.100:3306 max_fails3 fail_timeout5;server 172.25.254.200:3306 max_fails3 fail_timeout5;}server {listen 3306;proxy_pass mariadb;}
}
[rootwebserver nginx]# nginx -s reload[rootwebserver nginx]# mysql -ulee -plee -h172.25.254.10 -eselect server_id;
-------------
| server_id |
-------------
| 100 |
-------------
[rootwebserver nginx]# mysql -ulee -plee -h172.25.254.10 -eselect server_id;
-------------
| server_id |
-------------
| 200 |3.19 部署fastcgi泵整合nginx
CGI的由来 最早的Web服务器只能简单地响应浏览器发来的HTTP请求并将存储在服务器上的HTML文件返回给浏 览器也就是静态html文件但是后期随着网站功能增多网站开发也越来越复杂以至于出现动态技术比如像php(1995年)、java(1995)、python(1991)语言开发的网站但是nginx/apache服务器并不能直接运行 php、java这样的文件apache实现的方式是打补丁但是nginx缺通过与第三方基于协议实现即通过某种特定协议将客户端请求转发给第三方服务处理第三方服务器会新建新的进程处理用户的请求处理完成后返回数据给Nginx并回收进程最后nginx在返回给客户端那这个约定就是通用网关接口(common gateway interface简称CGI)CGI协议 是web服务器和外部应用程序之间的接口标准是cgi程序和web服务器之间传递信息的标准化接口。为什么会有FastCGI CGI协议虽然解决了语言解析器和 Web Server 之间通讯的问题但是它的效率很低因为 Web Server每收到一个请求都会创建一个CGI进程PHP解析器都会解析php.ini文件初始化环境请求结束的时候再关闭进程对于每一个创建的CGI进程都会执行这些操作所以效率很低而FastCGI是用来提高CGI性能的FastCGI每次处理完请求之后不会关闭掉进程而是保留这个进程使这个进程可以处理多个请求。这样的话每个请求都不用再重新创建一个进程了大大提升了处理效率。什么是PHP-FPMPHP-FPM(FastCGI Process Manager FastCGI进程管理器)是一个实现了Fastcgi的程序并且提供进程管理的功能。 进程包括master进程和worker进程。master进程只有一个负责监听端口接受来自web server的请求 worker进程一般会有多个每个进程中会嵌入一个PHP解析器进行PHP代码的处理。 FastCGI配置指令Nginx基于模块ngx_http_fastcgi_module实现通过fastcgi协议将指定的客户端请求转发至php-fpm处理其配置指令如下 fastcgi_pass address:port;
#转发请求到后端服务器address为后端的fastcgi server的地址可用位置location, if in
location
fastcgi_index name;
#fastcgi默认的主页资源示例fastcgi_index index.php;
fastcgi_param parameter value [if_not_empty];
#设置传递给FastCGI服务器的参数值可以是文本变量或组合可用于将Nginx的内置变量赋值给自定义
key
fastcgi_param REMOTE_ADDR $remote_addr; #客户端源IP
fastcgi_param REMOTE_PORT $remote_port; #客户端源端口
fastcgi_param SERVER_ADDR $server_addr; #请求的服务器IP地址
fastcgi_param SERVER_PORT $server_port; #请求的服务器端口
fastcgi_param SERVER_NAME $server_name; #请求的server name
Nginx默认配置示例
location ~ \.php$ {
root /scripts;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; #默认脚本路径
#fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params; #此文件默认系统已提供,存放的相对路径为
prefix/conf
} 示例 编译安装更方便自定义参数或选项所以推荐大家使用源码编译 官方网站www.php.net ###源码编译php
[rootwebserver ~]# cd ~
[rootwebserver ~]# dnf install -y bzip2 systemd-devel libxml2-devel sqlite-devel
[rootwebserver ~]# dnf install -y libpng-devel libcurl-devel
[rootwebserver ~]# ls
anaconda-ks.cfg nginx-1.24.0 nginx-1.26.1.tar.gz php-8.3.9
echo-nginx-module-0.63 nginx-1.24.0.tar.gz oniguruma-6.9.6-1.el9.6.x86_64.rpm php-8.3.9.tar.gz
echo-nginx-module-0.63.tar.gz nginx-1.26.1 oniguruma-devel-6.9.6-1.el9.6.x86_64.rpm test.png#两个包不一样
[rootwebserver ~]# dnf update oniguruma-6.9.6-1.el9.6.x86_64.rpm
[rootwebserver ~]# dnf install oniguruma-devel-6.9.6-1.el9.6.x86_64.rpm
[rootwebserver ~]# tar zxf php-8.3.9.tar.gz
[rootwebserver ~]# cd php-8.3.9/
./configure --prefix/usr/local/php --with-config-file-path/usr/local/php/etc --enable-fpm --with-fpm-usernginx --with-fpm-groupnginx --with-curl --with-iconv --with-mhash --with-zlib --with-openssl --enable-mysqlnd --with-mysqli --with-pdo-mysql --disable-debug --enable-sockets --enable-soap --enable-xml --enable-ftp --enable-gd --enable-exif --enable-mbstring --enable-bcmath --with-fpm-systemd
[rootwebserver ~]# make make install
#等待ing~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~[rootwebserver php-8.3.9]# cd /usr/local/php/
[rootwebserver php]# cd etc/
[rootwebserver etc]# cp -p php-fpm.conf.default php-fpm.conf
[rootwebserver etc]# vim php-fpm.conf
pid run/php-fpm.pid #指定pid文件存放位置,给代码去掉注释
[rootwebserver etc]# cd php-fpm.d/
[rootwebserver php-fpm.d]# cp www.conf.default www.conf -p
[rootwebserver php-fpm.d]# vim www.conf
listen 0.0.0.0:9000[rootwebserver php-fpm.d]# cd ~/php-8.3.9/
[rootwebserver php-8.3.9]# cp php.ini-production /usr/local/php/etc/php-ini[rootwebserver php-8.3.9]# cd sapi/fpm/
[rootwebserver fpm]# cp php-fpm.service /lib/systemd/system
[rootwebserver fpm]# cd /lib/systemd/system
[rootwebserver system]# vim php-fpm.service
...
#ProtectSystemfull[rootwebserver system]# systemctl daemon-reload
[rootwebserver system]# systemctl enable --now php-fpm.service [rootwebserver nginx]# cd /usr/local/nginx/
[rootwebserver nginx]# vim html/index.php
?phpphpinfo ();
?
[rootwebserver nginx]# vim conf.d/vhosts.conf
server {listen 80;server_name www.timinglee.org;error_log /var/log/nginx/error.log;location ~ \.php$ {fastcgi_pass 127.0.0.1:9000;fastcgi_index index.php;fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;include fastcgi.conf;}
}
[rootwebserver nginx]# nginx -s reload3.20 利用memcache加速php 软件下载http://pecl.php.net/package/memcache ###memcache整合php
[rootwebserver nginx]# dnf install memcached -y
[rootwebserver nginx]# vim /etc/sysconfig/memcached
...
OPTIONS-l 0.0.0.0,::1
[rootwebserver nginx]# systemctl enable --now memcached.service
[rootwebserver ~]# ls
anaconda-ks.cfg nginx-1.24.0 oniguruma-6.9.6-1.el9.6.x86_64.rpm test.png
echo-nginx-module-0.63 nginx-1.24.0.tar.gz oniguruma-devel-6.9.6-1.el9.6.x86_64.rpm
echo-nginx-module-0.63.tar.gz nginx-1.26.1 php-8.3.9
memcache-8.2.tgz nginx-1.26.1.tar.gz php-8.3.9.tar.gz
[rootwebserver ~]# tar zxf memcache-8.2.tgz
[rootwebserver ~]# cd memcache-8.2/
[rootwebserver memcache-8.2]# cp example.php memcache.php /usr/local//nginx/html/
[rootwebserver memcache-8.2]# cd /usr/local/nginx/
[rootwebserver nginx]# ls html/
50x.html example.php index.html index.php memcache.php[rootwebserver nginx]# vim html/memcache.php
...
define(ADMIN_USERNAME,admin); // Admin Username
define(ADMIN_PASSWORD,lee); // Admin Password#$MEMCACHE_SERVERS[] mymemcache-server1:11211; // add more as an array
$MEMCACHE_SERVERS[] 127.0.0.1:11211; // add more as an array...###php整合memcache[rootwebserver nginx]# vim ~/.bash_profile
export PATH$PATH:/usr/local/nginx/sbin:/usr/local/php/bin:/usr/local/php/sbin
[rootwebserver nginx]# source ~/.bash_profile
[rootwebserver nginx]# cd ~/memcache-8.2/
[rootwebserver memcache-8.2]# dnf install autoconf -y
[rootwebserver memcache-8.2]# phpize
[rootwebserver memcache-8.2]# ./configure make make install[rootwebserver memcache-8.2]# cd /usr/local/php/lib/php/extensions/no-debug-non-zts-20230831/
[rootwebserver no-debug-non-zts-20230831]# ls
memcache.so opcache.so[rootwebserver no-debug-non-zts-20230831]# systemctl restart php-fpm.service
[rootwebserver no-debug-non-zts-20230831]# cd /usr/local/php/etc/
[rootwebserver etc]# vim php-ini
...975 extensionmemcache
...990 date.timezone Asia/Shangha
... 3.21 memcache实现高速缓存 在我们安装的nginx中默认不支持memc和srcache功能需要借助第三方模块来让nginx支持此功能所以nginx需要重新编译[rootwebserver nginx]# mv conf.d /mnt
[rootwebserver nginx]# mv conf/nginx.conf /mnt
[rootwebserver nginx]# rm -rf /usr/local/nginx/
[rootwebserver nginx]# cd ~
[rootwebserver ~]# tar zxf memc-nginx-module-0.20.tar.gz
[rootwebserver ~]# tar zxf srcache-nginx-module-0.33.tar.gz
[rootwebserver ~]# cd nginx-1.26.1/
[rootwebserver nginx-1.26.1]# ./configure --prefix/usr/local/nginx --usernginx --groupnginx --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/root/memc-nginx-module-0.20 --add-module/root/srcache-nginx-module-0.33 --add-module/root/echo-nginx-module-0.63[rootwebserver nginx]# cp /mnt/nginx.conf conf/nginx.conf
[rootwebserver nginx]# vim conf.d/vhost.conf
upstream memcache {server 127.0.0.1:11211;keepalive 512;
}
server {listen 80;server_name www.timinglee.org;error_log /var/log/nginx/error.log;location /memc {memc_connect_timeout 100ms;memc_send_timeout 100ms;memc_read_timeout 100ms;set $memc_key $query_string; #使用内置变量$query_string来作为keyset $memc_exptime 300; #缓存失效时间300秒memc_pass memcache;}location ~ \.php$ {set $key $uri$args; #设定key的值srcache_fetch GET /memc $key; #检测mem中是否有要访问的phpsrcache_store PUT /memc $key; #缓存为加载的php数据fastcgi_pass 127.0.0.1:9000;fastcgi_index index.php;fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;include fastcgi.conf;}
}[rootwebserver nginx]# nginx -s reload
[rootwebserver nginx]# vim html/index.php#测试
[rootwebserver nginx]# ab -n1000 -c50 http://www.timinglee.org/index.php
...
Complete requests: 1000
Failed requests: 0 #not have 失败
...
3.22 nginx二次开发版本 Nginx 是俄罗斯人发明的 Lua 是巴西几个教授发明的中国人章亦春把 LuaJIT VM 嵌入到 Nginx 中实现了 OpenResty 这个高性能服务端解决方案 OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。 OpenResty® 通过汇聚各种设计精良的 Nginx 模块主要由 OpenResty 团队自主开发从而将Nginx有效地变成一个强大的通用 Web 应用平台。这样Web 开发人员和系统工程师可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块快速构造出足以胜任 10K 乃至 1000K 以上单机并发连接的高性能 Web 应用系统。 OpenResty 由于有功能强大且方便的的API,可扩展性更强,如果需要实现定制功能,OpenResty是个不错的选择
官网: http://openresty.org/cn/
[rootwebserver nginx]# systemctl stop nginx.service
[rootwebserver nginx]# cd ~
[rootwebserver ~]# rm -rf /usr/local/nginx/
[rootwebserver ~]# ls
anaconda-ks.cfg memc-nginx-module-0.20.tar.gz package.xml
echo-nginx-module-0.63 nginx-1.26.1 php-8.3.9
echo-nginx-module-0.63.tar.gz nginx-1.26.1.tar.gz php-8.3.9.tar.gz
memcache-8.2 oniguruma-6.9.6-1.el9.6.x86_64.rpm srcache-nginx-module-0.33
memcache-8.2.tgz oniguruma-devel-6.9.6-1.el9.6.x86_64.rpm srcache-nginx-module-0.33.tar.gz
memc-nginx-module-0.20 openresty-1.25.3.1.tar.gz
[rootwebserver ~]# tar zxf openresty-1.25.3.1.tar.gz
[rootwebserver ~]# cd openresty-1.25.3.1/
[rootwebserver openresty-1.25.3.1]# dnf -y install gcc pcre-devel openssl-develperl
[rootwebserver openresty-1.25.3.1]# useradd -r -s /sbin/nologin nginx
[rootwebserver openresty-1.25.3.1]# ./configure --prefix/usr/local/openresty --usernginx --groupnginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module[rootwebserver openresty-1.25.3.1]# make make install
[rootwebserver openresty-1.25.3.1]# openresty -t
nginx: the configuration file /usr/local/openresty/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/openresty/nginx/conf/nginx.conf test is successful
[rootwebserver openresty-1.25.3.1]# openresty