nginx

高性能WEB服务NGINX

image-20211211104817647

1.Web 服务和 Http协议

1.3超文本传输协议

万维网客户与服务器遵守的协议:超文本协议,HTTP是应用层协议,使用TCP传输层进行可靠的传输

HTML:html与txt一样是一种文档,但是这种文档专供浏览器上为浏览器用户提供统一的界面呈现的统一规约,且具备结构化特征。这是提txr不具备的

1.3.2打开浏览器的过程

面试

image-20211207204854458

1、首先将网址解析成地址(DNS解析:迭代,递归,DNS 缓存)

2、与对方服务器进行连接(三次握手,四次挥手)

3、发送HTTP请求(请求报文响应报文),跳转HTTPS

4、构建页面。

1.3.3 HTTP服务通信过程

HTTP(HyperText Transfer Protocol,超文本传输协议)是一种用于分布式、协作式和超媒体信息系统的应用层协议。

HTTP 服务通信过程

image-20211207205241421

1、首先搭建http服务器,用Ngonx,客户端(浏览器)

2、通讯过成:服务器s1s2s3,客户端c1c2c3,服务器s4.此时,连接成功,可以接收数据与发送数据了

客户端用于服务器段程序


HTTP 协议分层

image-20211207205318818

1.3.4 HTTP 相关技术

1.3.4.1 WEB开发语言

HTTP:hyper,,,,,应用层协议,默认端口:80/tcp

安装nginx

 yum -y install nginx
 systemctl start nginx

三种不同的前端语言(了解)

html

Hyper Text Markup Language 超文本标记语言,编程语言,主要负责实现页面的结构

CSS

Cascading Style Sheet 层叠样式表, 定义了如何显示(装扮) HTML 元素,如918 页面变黑色

Js

javascript,实现网页的动画效果,但实属于静态资源

1.3.4.2 MIME

MIME : Multipurpose Internet Mail Extensions 多用途互联网邮件扩展:通过定义资源类型

文件 /etc/mime.types ,来自于mailcap包

MIME格式:type/subtype

1.2.4.3 URL和URI

浏览器框输入:

URI:统一资源标识,分为URL和URN

URN:Uniform Resource Naming,统一资源命名

URL:Uniform Resorce Locator,统一资源定位符,用于描述某服务器某特定资源位置

image-20211208111208681

1.3.4.4网站访问量

面试

网站访问量的指标

IP地址:相同客户机IP地址只计算一次,是衡量网站流量的重要指标

PV:访问几次,

UV: 独立用户访客

1.3.5HTTP工作机制

一次http事物包括(连上就断)

  • http请求
  • http响应

Web资源:web resource, 一个网页由多个资源(文件)构成,打开一个页面,通常会有多个资源展示出来,但是每个资源都要单独请求。因此,一个"Web 页面”通常并不是单个资源,而是一组资源的集合

资源类型

  • 静态文件:无需服务端做出额外处理,服务器端和客户端的文件内容相同
    常见文件后缀:.html, .txt, .jpg, .js, .css, .mp3, .avi
  • 动态文件:服务端执行程序,返回执行的结果,服务器端和客户端的文件内容不相同
    常见文件后缀:.php, .jsp ,.asp

HTTP连接请求

浏览器打开网站后像网站发起连接请求,获取首页面,下载首页面后再次发起请求,下载其他的相关资源,为提高效率,并行下载,持久连接(效率不高需要排队)采用管道,同时下载。

提高HTTP连接性能

  • 并行连接:通过多条TCP连接发起并发的HTTP请求
  • 持久连接:keep-alive,重用TCP连接,以消除连接和关闭的时延,以事务个数和时间来决定是否关闭连接
  • 管道化连接:通过共享TCP连接,发起并发的HTTP请求
  • 复用的连接:交替传送请求和响应报文(实验阶段)

1.3.6 HTTP 协议版本

面试重点

http协议版本的1.0 1.1 2.0的区别

常见响应码有哪些,并解释意思

apahche三种工作模式/与nginx有什莫区别?

1.3.7 HTTP 请求访问的完整过程

一次完整的http请求处理过程

1、建立连接:接收或拒绝连接请求

2、接收请求:方式IO,接收客户端请求报文中对某资源的一次请求的过程

  • 单线程
  • 多线程
  • 复用的IO 结构:启动一个进程,同时响应N个连接请求
  • 复用的多线程io结构:启动M个进程,每个进程响应N个连接请求,同时接收M*N个请求

3、处理请求:服务器对请求报文进行解析,并获取请求的资源及请求方法等相关信息,根据方法,资源,首部和可选的主体部分对请求进行处理

4、访问资源:服务器获取请求报文中请求的资源web服务器,即存放了web资源的服务器,负责向请求者提供对方请求的静态资源,或动态运行后生成的资源

5、构建响应报文:一旦Web服务器识别除了资源,就执行请求方法中描述的动作,并返回响应报文。响应报文中 包含有响应状态码、响应首部,如果生成了响应主体的话,还包括响应主体

1)响应实体:

2)URL重定向

3)MIME类型:

6、发送响应报文:Web服务器通过连接发送数据时也会面临与接收数据一样的问题。服务器可能有很多条到各个客户端的连接,有些是空闲的,有些在向服务器发送数据,还有一些在向客户端回送响应数据。服务器要记录连接的状态,还要特别注意对持久连接的处理。对非持久连接而言,服务器应该在发送了整条报文之后,关闭自己这一端的连接。对持久连接来说,连接可能仍保持打开状态,在这种情况下,服务器要正确地计算Content-Length首部,不然客户端就无法知道响应什么时候结束

7、记录日志

最后,当事务结束时,Web服务器会在日志文件中添加一个条目,来描述已执行的事务

1.4 http 协议及报文头部结构

http协议:http/0.9, http/1.0, http/1.1, http/2.0,http/3.0

http协议:stateless 无状态, 服务器无法持续追踪访问者来源

解决http协议无状态方法

cookie 客户端存放
session 服务端存放

http事务:一次访问的过程

请求:request
响应:response

HTTP报文结构

协议查看或分析的工具:tcpdump, wireshark,tshark

1.4.1 HTTP请求报文

image-20211207214117805

request报文格式:文本

开始行:方法,url,版本

首部行:键值对,浏览器字段名+浏览器版本信息

实体主体: 本机文件

image-20211209220622460

1.4.2 HTTP响应报文

image-20211207214146864

1.4.3 HTTP报文格式详解

1.4.3.1 Method 方法

1.4.3.2 version版本

1.4.3.3 status 状态码

http协议状态码分类

1xx:100-101 信息提示
2xx:200-206 成功
3xx:300-307 重定向
4xx:400-415 错误类信息,客户端错误
5xx:500-505 错误类信息,服务器端错误

http协议常用的状态码

200: 成功,请求数据通过响应报文的entity-body部分发送;OK
301: 请求的URL指向的资源已经被删除;但在响应报文中通过首部Location指明了资源现在所处的新位置;Moved Permanently
302: 响应报文Location指明资源临时新位置 Moved Temporarily
304: 客户端发出了条件式请求,但服务器上的资源未曾发生改变,则通过响应此响应状态码通知客户端;Not Modified
307: 浏览器内部重定向
401: 需要输入账号和密码认证方能访问资源;Unauthorized
403: 请求被禁止;Forbidden
404: 服务器无法找到客户端请求的资源;Not Found
499: 客户端读超时关闭连接的错误码 499是客户端读超时关闭连接造成的,推荐从超时时间或者优化响应速度入手,web服务器发现客户端主动关闭连接后,记录到access日志中的。可能是客户端接收响应超时了,可以先在客户端统计下是不是这个原因,再调查为什么会导致超时
500: 服务器内部错误;Internal Server Error,比如:cgi程序没有执行权限
502: 代理服务器从后端服务器收到了一条伪响应,如无法连接到网关;Bad Gateway,比如后端服务端口没有打开
503: 服务不可用,临时服务器维护或过载,服务器无法处理请求,比如:php服务停止,无法处理php程序
504: 网关超时,或者后端服务器无回应报文

1.4.3.4 reason-phrase原因短语

状态码所标记的状态的简要描述

1.4.3.5 headers首部字段头

1.4.4cookie和session

cookie:登陆验证,放于首部字段,是小文本内容,解决http的无状态,

cookie实现

yum -y install  httpd php
systenctl enable --now httpd php
可以通过php程序支持

cookie的获取过程

image-20211208115407487

#第一次请求过程
浏览器第一次发送请求时,不会携带任何cookie信息
服务器接收到请求之后,发现请求中没有任何cookie信息
服务器生成和设置一个cookie.并将此cookie设置通过set_cookie的首部字段保存在响应报文中返回给浏
览器
浏览器接收到这个响应报文之后,发现里面有cookie信息,浏览器会将cookie信息保存起来
#第二次及其之后的过程
当浏览器第二次及其之后的请求报文中自动 cookie的首部字段携带第一次响应报文中获取的cookie信息
服务器再次接收到请求之后,会发现请求中携带的cookie信息,这样的话就认识是谁发的请求了
之后的响应报文中不会再添加set_cookie首部字段

cookie主要用于以下三个方面

  • 会话状态管理
  • 个性化设置
  • 浏览器跟踪行为

Cookie 技术通过在请求和响应报文中写入 Cookie 信息来控制客户端的状态。当服务器收到HTTP请求时,服务器可以在响应头里面添加一个Set-Cookie选项。浏览器收到响应后通常会保存下Cookie,之后对该服务器每一次请求中都通过Cookie请求头部将Cookie信息发送给服务器。服务器端发现客户端发送过来的 Cookie 后,会去检查究竟是从哪一个客户端发来的连接请求,然后对比服务器上的记录,最后得到之前的状态信息.另外,Cookie的过期时间、域、路径、有效期、适用站点都可以根据需要来指定。

静态资源不会有cookie

1.4.4.2 Session

image-20211208144726027

session是相对于cookie的另外一个状态保持的解决方案,它是通过服务器来保持状态的。session指的是服务器上为每个客户端所开辟的独立存储空间,在其中保存的信息就是用于保存状态的。

每个session都有一个sessionId,每个人都有独立的sessionID,里边存放内容由程序员决定,这个ID存放有两种方式:

1、通过URL存取,

2、通过cookie存取(Tomcat默认如此),

session 的工作流程

第一次请求:

  • 浏览器发起第一次请求的时候可以携带一些信息(比如: 用户名/密码) cookie中没有任何信息
  • 当服务器接收到这个请求之后,进行用户名和密码的验证,验证成功后则可以设置session信息
  • 在设置session信息的同时(session信息保存在服务器端) .服务器会在响应头中设置一个随机的session id的cookie信息
  • 客户端(浏览器)在接收到响应之后,会将cookie信息保存起来(保存session id的信息)

第二次及其之后的请求:

  • 第二次及其之后的请求都会携带session id信息
  • 当服务器接收到这个请求之后,会获取到session id信息,然后进行验证
  • 验证成功,则可以获取session信息(session信息保存在服务器端)

1.4.4.3cookie和session比较

ccookie和session的不同与相同

  • cookie通常是在服务器生成,但也可以在客户端生成,session是在服务器端生成的
  • session 将数据信息保存在服务器端,可以是内存,文件,数据库等多种形式,cookie 将数据保存在客户端的内存或文件中
  • 单个cookie保存的数据不能超过4K,每个站点cookie个数有限制,比如IE8为50个、Firefox为50个、Opera为30个;session存储在服务器,没有容量限制
  • cookie存放在用户本地,可以被轻松访问和修改,安全性不高;session存储于服务器,比较安全
  • cookie有会话cookie和持久cookie,生命周期为浏览器会话期的会话cookie保存在缓存,关闭浏
    览器窗口就消失,持久cookie被保存在硬盘,知道超过设定的过期时间;随着服务端session存储压力增大,会根据需要定期清理session数据
  • session中有众多数据,只将sessionID这一项可以通过cookie发送至客户端进行保留,客户端下次访问时,在请求报文中的cookie会自动携带sessionID,从而和服务器上的的session进行关联

cookie缺点:

session 缺点:
1、不容易在多台服务器之间共享,可以使用session绑定,session复制,session共享解决
2、session存放在服务器中,所以session如果太多会非常消耗服务器的性能
cookie和session各有优缺点,在大型互联网系统中,单独使用cookie和session都是不可行的

1.5 Web相关工具(客户端服务器)

Web服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,可以处理浏览器等Web客户端的请求并返回相应响应,也可以放置网站文件,让全世界浏览;可以放置数据文件,让全世界下载。目前最主流的三个Web服务器是Apache、 Nginx 、IIS。

格式

links [option]...[url]...

1.5.2 wget

1.5.3 curl

1.6 Web 服务介绍

1.6.1 Apache 经典的 Web 服务端

1.6.1.1 Apache prefork 模型:从10k问题

预派生模式,有一个主控制进程,然后生成多个子进程,每个子进程有一个独立的线程响应用户请求,相对比较占用内存,但是比较稳定,可以设置最大和最小进程数,是最古老的一种模式,也是最稳定的模式,适用于访问量不是很大的场景

优点:稳定

缺点:每个用户请求需要对应开启一个进程,占用资源较多,并发性差,不适用于高并发场景

image-20211208161114511

1.6.1.2 Apache worker 模型

一种多进程和多线程混合的模型,有一个控制进程,启动多个子进程,每个子进程里面包含固定的线程,使用线程程来处理请求,当线程不够使用的时候会再启动一个新的子进程,然后在进程里面再启动线程处理请求,由于其使用了线程处理请求,因此可以承受更高的并发。

优点:相比prefork 占用的内存较少,可以同时处理更多的请求

缺点:使用keepalive的长连接方式,某个线程会一直被占据,即使没有传输数据,也需要一直等待到超时才会被释放。如果过多的线程,被这样占据,也会导致在高并发场景下的无服务线程可用。(该问题在prefork模式下,同样会发生)

image-20211208161232883

1.6.1.3 Apache event模型

优点:单线程响应多请求,占据更少的内存,高并发下表现更优秀,会有一个专门的线程来管理keepalive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放

缺点:没有线程安全控制

image-20211208161532821

主进程开启子线程,子进程开线程。监听线程要配线程给任务请求

1.6.2 Nginx-高性能的 Web 服务端

突出优势:高并发、以功能丰富:作为反向代理服务器或者web服务器、 支持第三方的功能扩展。

基于Nginx的工作场景:

image-20211210110719787

1.6.3 用户访问体验和性能

1.6.3.1 用户访问体验统计

互联网存在用户速度体验的1-3-10原则,即1秒最优,1-3秒较优,3~10秒比较慢,10秒以上用户无法接受。用户放弃一个产品的代价很低,只是换一个URL而已。

1.6.3.2 影响用户体验的因素

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

1.6.4 服务端 I/O 流程

I/O在计算机中指Input/Output,

IOPS (Input/Output Per Second)每秒的输入输出量【读写次数】

一次完整的I/O是用户空间的进程数据与内核空间的内核数据的报文的完整交换,但是由于内核空间与用户空间是严格隔离的,所以其数据交换过程中不能由用户空间的进程直接调用内核空间的内存数据,而是需要经历一次从内核空间中的内存数据copy到用户空间的进程内存当中,所以简单说I/O就是把数据从内核空间中的内存数据复制到用户空间中进程的内存当中。

Linux 的 I/O

  • 磁盘I/O
  • 网络I/O : 一切皆文件,本质为对socket文件的读写

1.6.4.1 磁盘 I/O(优化幅度限)

磁盘IO是进程向内核发起调用,请求磁盘上的某个资源比如html文件,然后内核通过相应的驱动程序将目标文件加载到内村空间,加载完成之后把数据从内核内存在复制给进程内村,如果比较打的数据也需要等待。

1.6.4.2 网络 I/O(重点优化)

网络通信就是网络协议栈到用户空间进程的IO就是网络IO

image-20211207222325018

image-20211210153052830

网络I/O 处理过程

获取请求数据,客户端与服务器建立连接发出请求,服务器接受请求(1-3)构建响应,当服务器接收完请求,并在用户空间处理客户端的请求,直到构建响应完成(4)返回数据,服务器将已构建好的响应再通过内核空间的网络 I/O 发还给客户端(5-7)

不同磁盘网络I/O

每次I/O,都要经过两个阶段第一步:将数据从文件加载到内和空间,等待数据准备完成时间较长。、第二步:将数据从内核缓冲区复制到用户空间的进程的内存中,时间较短

1.7 I/O 模型

1.7.1 I/O 模型相关概念

同步/异步:关注的是消息通信机制,即调用者在等待一件事情的处理结果时,被调用者是否提供完成状态的通知。

同步:synchronous,被调用者并不提供事件的处理结果相关的通知消息,需要调用者主动询问事情是否处理完成

异步:asynchronous,被调用者通过状态、通知或回调机制主动通知调用者被调用者的运行状态阻塞/非阻塞:关注调用者在等待结果返回之前所处的状态

阻塞:blocking,指IO操作需要彻底完成后才返回到用户空间,调用结果返回之前,调用者被挂起,干不了别的事情。

非阻塞:nonblocking,指IO操作被调用后立即返回给用户一个状态值,而无需等到IO操作彻底完成,在最终的调用结果返回之前,调用者不会被挂起,可以去做别的事情。

image-20211210155849222

image-20211210124924471

image-20211210124944040

1.7.2 网络 I/O 模型

网络分类:阻塞型、非阻塞型、复用型、信号驱动型、异步
参看:《UNIX网络编程 卷1:套接字联网API 》(美)W. Richard Stevens 著

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

在网络I/O的第一阶段与第二阶段:nginx一直等待

image-20211210125029217

阻塞IO模型是最简单的I/O模型,用户线程在内核进行IO操作时被阻塞
用户线程通过系统调用read发起I/O读操作,由用户空间转到内核空间。内核等到数据包到达后,然后将接收的数据拷贝到用户空间,完成read操作
用户需要等待read将数据读取到buffer后,才继续处理接收的数据。整个I/O请求的过程中,用户线程是被阻塞的,这导致用户在发起IO请求时,不能做任何事情,对CPU的资源利用率不够
优点:程序简单,在阻塞等待数据期间进程/线程挂起,基本不会占用 CPU 资源
缺点:每个连接需要独立的进程/线程单独处理,当并发请求量大时为了维护程序,内存、线程切换开销较大,apache 的preforck使用的是这种模式。

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

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

image-20211210125128734

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

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

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

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

上面的模型中,每一个文件描述符对应的IO是由一个线程监控和处理
多路复用IO指一个线程可以同时(实际是交替实现,即并发完成)监控和处理多个文件描述符对应各自的IO,即复用同一个线程
一个线程之所以能实现同时处理多个IO,是因为这个线程调用了内核中的SELECT,POLL或EPOLL等系统调用,从而实现多路复用IO

image-20211210125255486

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

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

image-20211210125433708

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

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

在信号驱动式 I/O 模型中,应用程序使用套接口进行信号驱动 I/O,并安装一个信号处理函数,进程继续运行并不阻塞当数据准备好时,进程会收到一个 SIGIO 信号,可以在信号处理函数中调用 I/O 操作函数处理数据。

优点:线程并没有在等待数据时被阻塞,内核直接返回调用接收信号,不影响进程继续处理其他请求因此可以提高资源的利用率
缺点:信号 I/O 在大量 IO 操作时可能会因为信号队列溢出导致没法通知

异步阻塞:程序进程向内核发送IO调用后,不用等待内核响应,可以继续接受其他请求,内核收到进程请求后进行的IO如果不能立即返回,就由内核等待结果,直到IO完成后内核再通知进程。

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

image-20211210125614849

异步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。

1.7.3 五种 IO 对比

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

1.7.4 I/O 的具体实现方式

1.7.4.1 I/O常见实现

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

前三种

select:轮询并发限制1024:apach工作机制

poll:取消select并发限制

epoll:事件驱动机制,自动获取信息通知epoll,是nginx高并发原因

1selectselect库是在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没有本质上的区别,效效率和epoll相似5、IOCP: Windows系统上的实现方式,对应第5种(异步I/O)模型。6、/dev/poll:用于支持unix衍生平台的高效事件驱动模型,主要在Solaris 平台、HP/UX,该模型是sun公司在开发Solaris系列平台的时候提出的用于完成事件驱动机制的方案,它使用了虚拟的/dev/poll设备,开发人员将要见识的文件描述符加入这个设备,然后通过ioctl()调用来获取事件通知,因此运行在以上系列平台的时候请使用/dev/poll事件驱动机制。效率和epoll相似7、rtsig:不是一个常用事件驱动,最大队列1024,不是很常用8、eventport:该方案也是sun公司在开发Solaris的时候提出的事件驱动库,只是Solaris 10以上的版本,该驱动库可防止内核崩溃等情况的发生

1.7.4.2 常用I/O模型比较

cat /proc/sys/fs/dile-max#查看并发连接数free -h #看内存与并发数量关系

1.8 零拷贝

1.8.1 零拷贝介绍

1.8.1.1 传统 Linux中 I/O 的问题

image-20211210125851448

传统的 Linux 系统的标准 I/O 接口(read、write)是基于数据拷贝的,也就是数据都是 copy_to_user 或者 copy_from_user,这样做的好处是,通过中间缓存的机制,减少磁盘 I/O 的操作,但是坏处也很明显,大量数据的拷贝,用户态和内核态的频繁切换,会消耗大量的 CPU 资源,严重影响数据传输的性能,统计表明,在Linux协议栈中,数据包在内核态和用户态之间的拷贝所用的时间甚至占到了数据包整个处理流程时间的57.1%

1.8.1.2 什么是零拷贝

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

1.8.2 零拷页相关技术

1.8.2.1 MMAP ( Memory Mapping )

image-20211210130052252

mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问。
mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。
实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必再调用read,write等系统调用函数。相反,内核空间对这段区域的修改也直接反映用户空间,从而可以实现不同进程间的文件共享。

内存映射减少数据在用户空间和内核空间之间的拷贝操作,适合大量数据传输

image-20211210130113423

image-20211210130123580

上面左图为传统读写,右图为MMAP.两者相比mmap要比普通的read系统调用少了一次copy的过程。因为read调用,进程是无法直接访问kernel space的,所以在read系统调用返回前,内核需要将数据从内核复制到进程指定的buffer。但mmap之后,进程可以直接访问mmap的数据(page cache)。

1.8.2.2 SENDFILE sendfile

image-20211210130147998

1.8.2.3 DMA 辅助的 SENDFILE(硬件支持)

image-20211210130219265

2 Nginx 架构和安装

2.1.2 Nginx 功能介绍

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

2.2.3 基础特性

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

2.2.4 Web 服务相关的功能

  • 虚拟主机(server):一的物理服务器实现多个网站
  • 支持 keep-alive 和管道连接(利用一个连接做多次请求)
  • 访问日志(支持基于日志缓冲提高其性能)
  • url rewirte
  • 路径别名
  • 基于IP及用户的访问控制
  • 支持速率限制及并发数限制
  • 重新配置和在线升级而无须中断客户的工作进程

2.2 Nginx 架构和进程

2.2.1 Nginx 架构

image-20211210130507085

主进程master开启若干个子进程,一个进程处理多个请求,一个work就可以接受上万个请求,

2.2.2 Nginx 进程结构

web请求处理机制

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

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

Nginx是多进程组织模型,而且是一个由Master主进程和Worker工作进程组成

image-20211210130613621

主进程(master process)的功能:

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

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

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

image-20211210130727172

2.2.3 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等。操作系统提供了共享内存机制

image-20211210130827822

2.2.4 Nginx 启动和 HTTP 连接建立

image-20211210130918675

Nginx 启动时,Master 进程,加载配置文件Master 进程,初始化监听的 socketMaster 进程,fork 出多个 Worker 进程Worker 进程,竞争新的连接,获胜方通过三次握手,建立 Socket 连接,并处理请求

2.2.5 HTTP 处理过程

image-20211210131124937

2.3 Nginx 模块介绍

nginx 有多种模块

  • 核心模块:是 Nginx 服务器正常运行必不可少的模块,提供错误日志记录 、配置文件解析 、事件驱动机制 、进程管理等核心功能
  • 标准HTTP模块:提供 HTTP 协议解析相关的功能,比如: 端口配置 、 网页编码设置 、 HTTP响应头设置 等等
  • 可选HTTP模块:主要用于扩展标准的 HTTP 功能,让 Nginx 能处理一些特殊的服务,比如: Flash 多媒体传输 、解析 GeoIP 请求、 网络传输压缩 、 安全协议 SSL 支持等
  • 邮件服务模块:主要用于支持 Nginx 的 邮件服务 ,包括对 POP3 协议、 IMAP 协议和 SMTP协议的支持
  • Stream服务模块: 实现反向代理功能,包括TCP协议代理
  • 第三方模块:是为了扩展 Nginx 服务器应用,完成开发者自定义功能,比如: Json 支持、 Lua 支持等

nginx高度模块化,但其模块早期不支持DSO机制;1.9.11 版本支持动态装载和卸载

模块分类:

核心模块:core module标准模块: HTTP 模块: ngx_http_* HTTP Core modules   #默认功能 HTTP Optional modules #需编译时指定 Mail 模块: ngx_mail_* Stream 模块 ngx_stream_*第三方模块

image-20211210131352931

2.4 Nginx 安装

2.4.2 基于 yum 安装 Nginx

2.4.2.1 查看当前系统中的 nginx 版本

范例: 查看系统和EPEL的nginx版本

[root@loaclhost ~]# yum info nginxRepository extras is listed more than once in the configurationLast metadata expiration check: 3:00:02 ago on Fri 10 Dec 2021 10:15:21 AM CST.Installed PackagesName         : nginxEpoch        : 1Version      : 1.14.1Release      : 9.module+el8.4.0+542+81547229Architecture : x86_64Size         : 1.6 M#CentOS 7 需要提前配置好epel源[root@centos7 ~]#yum info nginxLoaded plugins: fastestmirrorLoading mirror speeds from cached hostfile * base: Available PackagesName       : nginxArch       : x86_64Epoch       : 1Version     : 1.16.1Release     : 1.el7Size       : 562 kRepo       : epel/7/x86_64Summary     : A high performance web server and reverse proxy serverURL         : http://nginx.org/License     : BSDDescription : Nginx is a web server and a reverse proxy server for HTTP, SMTP, POP3 and           : IMAP protocols, with a strong focus on high concurrency, performance and low           : memory usage.

2.4.2.2 官方包源安装最新版本 nginx

系统和EPEL源的中nignx版本较旧,可以安装官方源的最新版本

最好不用奇数版本,

官方包链接: http://nginx.org/en/linux_packages.html

官方 yum 源链接http://nginx.org/en/linux_packages.html#RHEL-CentOS

范例: 通过官方 yum 源安装nginx

[root@centos8 ~]#cat /etc/yum.repos.d/nginx.repo[nginx-stable]name=nginx stable repobaseurl=http://nginx.org/packages/centos/$releasever/$basearch/gpgcheck=1enabled=1gpgkey=https://nginx.org/keys/nginx_signing.keymodule_hotfixes=true[nginx-mainline]name=nginx mainline repobaseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/gpgcheck=1enabled=0gpgkey=https://nginx.org/keys/nginx_signing.keymodule_hotfixes=true#列出所有版本[root@centos8 ~]#yum list nginx --showduplicatesLast metadata expiration check: 0:01:08 ago on Tue 22 Sep 2020 12:01:59 PM CST.Available Packagesnginx.x86_64    1.16.0-1.el8.ngx                         nginx-stablenginx.x86_64    1:1.14.1-9.module_el8.0.0+184+e34fea82   AppStream   nginx.x86_64    1:1.16.1-1.el8.ngx                       nginx-stablenginx.x86_64    1:1.18.0-1.el8.ngx                       nginx-stable#查看版本信息[root@centos8 ~]#dnf info nginxLast metadata expiration check: 0:02:50 ago on Tue 22 Sep 2020 12:01:59 PM CST.Available PackagesName         : nginxEpoch       : 1Version     : 1.18.0Release     : 1.el8.ngxArchitecture : x86_64Size         : 806 kSource       : nginx-1.18.0-1.el8.ngx.src.rpmRepository   : nginx-stableSummary     : High performance web serverURL         : http://nginx.org/License     : 2-clause BSD-like licenseDescription : nginx [engine x] is an HTTP and reverse proxy server, as well as             : a mail proxy server.#安装指定版本[root@centos8 ~]#yum -y install nginx-1.18.0

2.4.2.3 检查安装

查看nginx安装包信息

[root@centos8 ~]#rpm -q nginxnginx-1.18.0-1.el8.ngx.x86_64[root@centos8 ~]#rpm -qi nginxName       : nginxEpoch       : 1Version     : 1.18.0Release     : 1.el8.ngxArchitecture: x86_64Install Date: Tue 22 Sep 2020 12:05:14 PM CSTGroup       : System Environment/DaemonsSize       : 3815084License     : 2-clause BSD-like licenseSignature   : RSA/SHA1, Tue 21 Apr 2020 11:19:19 PM CST, Key ID abf5bd827bd9bf62Source RPM : nginx-1.18.0-1.el8.ngx.src.rpmBuild Date : Tue 21 Apr 2020 11:07:57 PM CSTBuild Host : ip-10-1-17-47.eu-central-1.compute.internalRelocations : (not relocatable)Vendor     : Nginx, Inc.URL         : http://nginx.org/Summary     : High performance web serverDescription :nginx [engine x] is an HTTP and reverse proxy server, as well asa mail proxy server.[root@centos8 ~]#rpm -ql nginx/etc/logrotate.d/nginx/etc/nginx/etc/nginx/conf.d/etc/nginx/conf.d/default.conf/etc/nginx/fastcgi_params/etc/nginx/koi-utf/etc/nginx/koi-win/etc/nginx/mime.types/etc/nginx/modules/etc/nginx/nginx.conf/etc/nginx/scgi_params/etc/nginx/uwsgi_params/etc/nginx/win-utf/etc/sysconfig/nginx/etc/sysconfig/nginx-debug/usr/share/doc/nginx-1.18.0/COPYRIGHT/usr/share/man/man8/nginx.8.gz/usr/share/nginx/usr/share/nginx/html/usr/share/nginx/html/50x.html/usr/share/nginx/html/index.html/var/cache/nginx/var/log/nginx#带有自动日志切割功能[root@centos8 ~]#cat /etc/logrotate.d/nginx /var/log/nginx/*log {   create 0664 nginx root   daily   rotate 10   missingok     notifempty   compress   sharedscripts   postrotate       /bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true   endscript}

docker安装nginx

docker pull nginx:1.20.2dicker run -d --name nginx01 -p 80:80 nginx;1.20.2#镜像必须优化docker exec -it nginx01 bash#容器种命令特别少/usr/share/nginx/html#echo '<h1>baibaiabi<h1>' >index.html#覆盖源页面

2.4.2.4 nginx 程序用法帮助

使用安装完成的二进制文件nginx

[root@centos8 ~]#nginx -hnginx version: nginx/1.18.0Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]Options:  -?,-h         : this help  -v           : show version and exit  -V           : show version and configure options then exit #显示版本和编译参数  -t           : test configuration and exit #测试配置文件是否异常  -T           : test configuration, dump it and exit #测试并打印  -q           : suppress non-error messages during configuration testing #静默模式  -s signal     : send signal to a master process: stop, quit, reopen, reload #发送信号,reload信号 会生成新的worker,但master不会重新生成  -p prefix     : set prefix path (default: /etc/nginx/) #指定Nginx 目录  -c filename   : set configuration file (default: /etc/nginx/nginx.conf) #配置文件路径  -g directives : set global directives out of configuration file#设置全局指令,注意和配置文件不要同时配置,否则冲突

范例: nginx 命令使用

[root@centos8 ~]#nginx -g "worker_processes 6;"nginx: [emerg] "worker_processes" directive is duplicate in/apps/nginx/conf/nginx.conf:3[root@centos8 ~]#vim /apps/nginx/conf/nginx.conf                                                             #worker_processes 1;[root@centos8 ~]#nginx -g "worker_processes 6;"[root@centos8 ~]#ps aux|grep nginxroot        8843  0.0  0.0  41048   844 ?       Ss   18:53   0:00 nginx: master process nginx -g worker_processes 6;nginx       8844  0.0  0.4  74572  4832 ?       S    18:53   0:00 nginx: worker processnginx       8845  0.0  0.4  74572  4832 ?       S    18:53   0:00 nginx: worker processnginx       8846  0.0  0.4  74572  4832 ?       S    18:53   0:00 nginx: worker processnginx       8847  0.0  0.4  74572  4832 ?       S    18:53   0:00 nginx: worker processnginx       8848  0.0  0.4  74572  4832 ?       S    18:53   0:00 nginx: worker processnginx       8849  0.0  0.4  74572  4832 ?       S    18:53   0:00 nginx: worker processroot        8851  0.0  0.1  12108  1076 pts/1   S+   18:53   0:00 grep --color=auto nginx[root@centos8 ~]#nginx -s quit[root@centos8 ~]#ps aux|grep nginxroot        8858  0.0  0.1  12108  1100 pts/1   S+   18:54   0:00 grep --color=auto nginx#前台运行[root@centos8 ~]#nginx -g 'daemon off;'^C[root@centos8 ~]#

2.4.2.5 验证 Nginx

[root@centos8 ~]#nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successful[root@centos8 ~]#nginx -Vnginx version: nginx/1.18.0built by gcc 8.3.1 20190507 (Red Hat 8.3.1-4) (GCC) built with OpenSSL 1.1.1c FIPS  28 May 2019TLS SNI support enabledconfigure arguments: --pref

2.4.2.6 Nginx 启动文件

[root@centos8 ~]# cat /usr/lib/systemd/system/nginx.service[Unit]Description=nginx - high performance web serverDocumentation=http://nginx.org/en/docs/After=network-online.target remote-fs.target nss-lookup.targetWants=network-online.target[Service]Type=forkingPIDFile=/var/run/nginx.pidExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.confExecReload=/bin/kill -s HUP $MAINPIDExecStop=/bin/kill -s TERM $MAINPIDLimitNOFILE=100000[Install]WantedBy=multi-user.target

2.4.2.7 Nginx 配置文件

范例: 查看配置文件列表

[root@centos8 ~]#rpm -qc nginx/etc/logrotate.d/nginx/etc/nginx/conf.d/default.conf/etc/nginx/fastcgi_params/etc/nginx/koi-utf/etc/nginx/koi-win/etc/nginx/mime.types/etc/nginx/nginx.conf/etc/nginx/scgi_params/etc/nginx/uwsgi_params/etc/nginx/win-utf/etc/sysconfig/nginx/etc/sysconfig/nginx-debug[root@centos8 ~]#cat /etc/sysconfig/nginx# Configuration file for the nginx service.NGINX=/usr/sbin/nginxCONFFILE=/etc/nginx/nginx.conf[root@centos8 ~]#tree /etc/nginx//etc/nginx/├── conf.d│   └── default.conf├── fastcgi_params├── koi-utf├── koi-win├── mime.types├── modules -> ../../usr/lib64/nginx/modules├── nginx.conf├── scgi_params范例: 配置文件/etc/nginx/nginx.conf 默认配置2.4.2.8 启动 Nginx├── uwsgi_params└── win-utf2 directories, 9 files

范例: 配置文件/etc/nginx/nginx.conf 默认配置

[root@centos8 ~]#grep -Ev "^ *#|^$" /etc/nginx/nginx.conf user nginx;worker_processes  1;error_log /var/log/nginx/error.log warn;pid       /var/run/nginx.pid;events {   worker_connections  1024;}http {   include       /etc/nginx/mime.types;   default_type application/octet-stream;   log_format main  '$remote_addr - $remote_user [$time_local] "$request" '                      '$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';   access_log /var/log/nginx/access.log main;   sendfile       on;   keepalive_timeout  65;   include /etc/nginx/conf.d/*.conf;}

2.4.2.8 启动 Nginx

[root@centos8 ~]#systemctl enable --now nginxCreated symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.[root@centos8 ~]#systemctl status nginxnginx.service - nginx - high performance web server   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)   Active: active (running) since Tue 2020-09-22 12:24:19 CST; 4s ago     Docs: http://nginx.org/en/docs/ Process: 24584 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS) Main PID: 24585 (nginx)   Tasks: 2 (limit: 5882)   Memory: 2.4M   CGroup: /system.slice/nginx.service           ├─24585 nginx: master process /usr/sbin/nginx -c/etc/nginx/nginx.conf           └─24586 nginx: worker processSep 22 12:24:19 centos8.wangxiaochun.com systemd[1]: Starting nginx - high performance web server...Sep 22 12:24:19 centos8.wangxiaochun.com systemd[1]: Started nginx - high performance web server.[root@centos8 ~]#ps aux|grep nginxroot       24585  0.0  0.0  41312   860 ?       Ss   12:24   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.confnginx      24586  0.0  0.5  74896  4884 ?       S    12:24   0:00 nginx: worker processroot       24590  0.0  0.1  12108  1088 pts/0   S+   12:24   0:00 grep --color=auto nginx[root@centos8 ~]#pstree -p |grep nginx           |-nginx(24585)---nginx(24586)

2.4.2.9 访问 Nginx

image-20211210144105624

编译器介绍

源码安装需要提前准备标准的编译器,GCC的全称是(GNU Compiler collection),其有GNU开发,并以GPL即LGPL许可,是自由的类UNIX即苹果电脑Mac OS X操作系统的标准编译器,因为GCC原本只能处理C语言,所以原名为GNU C语言编译器,后来得到快速发展,可以处C++,Fortran,pascal,objectiveC,java以及Ada等其他语言,此外还需要Automake工具,以完成自动创建Makefile的工作,Nginx的一些模块需要依赖第三方库,比如: pcre(支持rewrite),zlib(支持gzip模块)和openssl(支持ssl模块)等。

2.4.3.1 编译安装 Nginx

官方源码包下载地址:

范例: 编译安装

[root@centos8 ~]#yum -y install gcc pcre-devel openssl-devel zlib-devel#装依赖的相关包[root@centos8 ~]#useradd -s /sbin/nologin nginx #创建一个给nginx使用的独有账号[root@centos8 ~]#cd /usr/local/src/[root@centos8 src]#wget http://nginx.org/download/nginx-1.18.0.tar.gz#下载源码[root@centos8 src]#tar xf nginx-1.18.0.tar.gz [root@centos8 src]#cd nginx-1.18.0/ #进到源码目录下[root@centos8 nginx-1.18.0]#./configure --prefix=/apps/nginx \  #config进行编译,后至佛那个安装路径--user=nginx \ #指定用户名--group=nginx \--with-http_ssl_module \  #启用某些功能--with-http_v2_module \--with-http_realip_module \--with-http_stub_status_module \--with-http_gzip_static_module \--with-pcre \--with-stream \--with-stream_ssl_module \--with-stream_realip_module[root@centos8 nginx-1.18.0]#make && make install#修改权限[root@centos8 nginx-1.18.0]#chown -R nginx.nginx /apps/nginx#改目录所有者与所属组

nginx完成安装以后,有四个主要的目录

#生成目录[root@centos8 nginx-1.18.0]#ll /apps/nginx/total 0drwxr-xr-x 2 root root 333 Sep 22 12:49 confdrwxr-xr-x 2 root root  40 Sep 22 12:49 htmldrwxr-xr-x 2 root root   6 Sep 22 12:49 logsdrwxr-xr-x 2 root root  19 Sep 22 12:49 sbinconf:保存nginx所有的配置文件,其中nginx.confnginx服务器的最核心最主要的配置文件,其他的.conf则是用来配置nginx相关的功能的,例如fastcgi功能使用的是fastcgi.conffastcgi_params两个文件,配置文件一般都有一个样板配置文件,是以.default为后缀,使用时可将其复制并将default后缀去掉即可。html目录中保存了nginx服务器的web文件,但是可以更改为其他目录保存web文件,另外还有一个50xweb文件是默认的错误页面提示页面。logs:用来保存nginx服务器的访问日志错误日志等日志,logs目录可以放在其他路径,比如/var/logs/nginx里面。sbin:保存nginx二进制启动脚本,可以接受不同的参数以实现不同的功能。

2.4.3.2 验证版本及编译参数

[root@centos8 nginx-1.18.0]#ls /apps/nginx/sbin/ #程序编译在此目录nginx[root@centos8 nginx-1.18.0]#ln -s /apps/nginx/sbin/nginx /usr/sbin/#将目录创建软连接指向/usr/sbin/#查看版本[root@centos8 ~]#nginx -v#查看编译结果nginx version: nginx/1.18.0#查看编译参数[root@centos8 ~]#nginx -Vnginx version: nginx/1.18.0built by gcc 8.3.1 20191121 (Red Hat 8.3.1-5) (GCC) built with OpenSSL 1.1.1c FIPS  28 May 2019TLS SNI support enabledconfigure arguments: --prefix=/apps/nginx --user=nginx --group=nginx --withhttp_ssl_module --with-http_v2_module --with-http_realip_module --withhttp_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream--with-stream_ssl_module --with-stream_realip_module

2.4.3.3 启动和停止 nginx 测试访问 web 界面

#启动nginx,默认是后台启动[root@centos8 ~]#nginx#浏览器可以访问看到下面图示[root@centos8 ~]#ss -ntlState             Recv-Q           Send-Q     Local Address:Port   Peer Address:Port           LISTEN            0                 100             127.0.0.1:25         0.0.0.0:*              LISTEN            0                 128               0.0.0.0:80         0.0.0.0:*              LISTEN            0                 128               0.0.0.0:22         0.0.0.0:*              LISTEN            0                 100                 [::1]:25             [::]:*              LISTEN            0                 128                 [::]:22             [::]:* #关闭nginx[root@centos8 ~]#nginx -s stop[root@centos8 ~]#ss -ntlState             Recv-Q           Send-Q   Local Address:Port   Peer Address:Port           LISTEN            0                 100           127.0.0.1:25         0.0.0.0:*              LISTEN            0                 128             0.0.0.0:22         0.0.0.0:*              LISTEN            0                 100               [::1]:25             [::]:*              LISTEN            0                 128               [::]:22             [::]:* 

image-20211210150312534

2.4.3.4 创建 Nginx 自启动文件

#复制同一版本的nginx的yum安装生成的service文件[root@centos8 ~]#vim /usr/lib/systemd/system/nginx.service [Unit]Description=nginx - high performance web serverDocumentation=http://nginx.org/en/docs/After=network-online.target remote-fs.target nss-lookup.targetWants=network-online.target[Service]Type=forkingPIDFile=/apps/nginx/run/nginx.pid #指定pid文件的目录,默认在logs目录下,可选配置ExecStart=/apps/nginx/sbin/nginx -c /apps/nginx/conf/nginx.conf#启动ExecReload=/bin/kill -s HUP $MAINPIDExecStop=/bin/kill -s TERM $MAINPIDLimitNOFILE=100000[Install]WantedBy=multi-user.target#创建pid文件存放的目录[root@centos8 ~]#mkdir /apps/nginx/run/#修改配置文件[root@centos8 ~]#vim /apps/nginx/conf/nginx.confpid   /apps/nginx/run/nginx.pid;

2.4.3.5 验证 Nginx 自启动文件

[root@centos8 ~]#systemctl daemon-reload [root@centos8 ~]#systemctl enable --now nginxCreated symlink /etc/systemd/system/multi-user.target.wants/nginx.service →              [root@centos8 ~]#ll /apps/nginx/run/total 4-rw-r--r-- 1 root root 5 Sep 22 13:01 nginx.pid[root@centos8 ~]#ss -ntlState             Recv-Q           Send-Q Local Address:Port   Peer Address:Port           LISTEN            0                 100         127.0.0.1:25          0.0.0.0:*              LISTEN            0                 128           0.0.0.0:80          0.0.0.0:*              LISTEN            0                 128           0.0.0.0:22          0.0.0.0:*              LISTEN            0                 100             [::1]:25             [::]:*              LISTEN            0                 128             [::]:22             [::]:* [root@centos8 ~]#systemctl stop nginx[root@centos8 ~]#systemctl status nginx● nginx.service - The nginx HTTP and reverse proxy server   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)   Active: inactive (dead) since Tue 2020-09-22 13:01:49 CST; 1s ago Process: 8113 ExecStart=/apps/nginx/sbin/nginx (code=exited, status=0/SUCCESS) Process: 8112 ExecStartPre=/apps/nginx/sbin/nginx -t (code=exited, status=0/SUCCESS) Process: 8110 ExecStartPre=/usr/bin/rm -f /apps/nginx/logs/nginx.pid (code=exited, status=0/SUCCESS) Main PID: 8115 (code=exited, status=0/SUCCESS)Sep 22 12:58:53 centos8.wangxiaochun.com systemd[1]: Starting The nginx HTTP and reverse proxy server...Sep 22 12:58:53 centos8.wangxiaochun.com nginx[8112]: nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is okSep 22 12:58:53 centos8.wangxiaochun.com nginx[8112]: nginx: configuration file /apps/nginx/conf/nginx.conf test is successfulSep 22 12:58:53 centos8.wangxiaochun.com systemd[1]: Started The nginx HTTP and reverse proxy server.Sep 22 13:01:49 centos8.wangxiaochun.com systemd[1]: Stopping The nginx HTTP and reverse proxy server...Sep 22 13:01:49 centos8.wangxiaochun.com systemd[1]: Stopped The nginx HTTP and reverse proxy server.[root@centos8 ~]#ss -ntlState             Recv-Q           Send-Q   Local Address:Port   Peer Address:Port           LISTEN            0                 100         127.0.0.1:25           0.0.0.0:*              LISTEN            0                 128           0.0.0.0:22           0.0.0.0:*              LISTEN            0                 100             [::1]:25             [::]:*              LISTEN            0                 128             [::]:22             [::]:*

2.4.4 自动化部署 nginx
2.4.4.1 实战案例: 一键编译安装 nginx 脚本

2.5 nginx 命令和信号

nginx 命令支持向其发送信号,实现不同功能

nginx 格式

nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]

选项说明

帮助: -? -h使用指定的配置文件: -c指定配置指令:-g指定运行目录:-p测试配置文件是否有语法错误:-t -T打印nginx的版本信息、编译信息等:-v -V发送信号: -s 示例: nginx -s reload

信号说明:

立刻停止服务:stop,相当于信号SIGTERM,SIGINT优雅的停止服务:quit,相当于信号SIGQUIT平滑重启,重新加载配置文件: reload,相当于信号SIGHUP重新开始记录日志文件:reopen,相当于信号SIGUSR1,在切割日志时用途较大平滑升级可执行程序:发送信号SIGUSR2,在升级版本时使用优雅的停止工作进程:发送信号SIGWINCH,在升级版本时使用

范例: 查看nginx帮助

[root@centos8 ~]#nginx -hnginx version: nginx/1.14.1Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]Options:  -?,-h         : this help  -v           : show version and exit  -V           : show version and configure options then exit

2.5.2 quit 实现worker进程优雅关闭

  • 设置定时器: worker_shutdown_timeout
http://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeoutSyntax: worker_shutdown_timeout time;Default: —Context: mainThis directive appeared in version 1.11.11.Configures a timeout for a graceful shutdown of worker processes. When the time expires, nginx will try to close all the connections currently open to facilitate shutdown.
  • 关闭监听句柄
  • 关闭空闲连接
  • 在循环中等待全部连接关闭
  • 退出nginx所有进程

2.5.3 reload 流程

image-20211210150705894

image-20211210150712036

利用 reload 可以实现平滑修改配置并生效

  • 向master进程发送HUP信号(reload命令)
  • master进程校验配置语法是否正确
  • master进程打开新的监听端口
  • master进程用新配置启动新的worker子进程
  • master进程向老worker子进程发送QUIT信号,老的worker对已建立连接继续处理,处理完才会优
  • 雅退出.未关闭的worker旧进程不会处理新来的请求
  • 老worker进程关闭监听句柄,处理完当前连接后结束进程

2.6 平滑升级和回滚

有时候需要对Nginx版本进行升级以满足对其功能的需求,例如添加新模块,需要新功能,而此时Nginx又在运行业务无法停止,这时就可以选择平滑升级

2.6.1 平滑升级流程

image-20211210150813583

image-20211210150819312

  • 将旧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

2.6.2 平滑升级和回滚案例

3 nginx 核心配置详解

3.1配置文件说明

nginx配置文件组成部分

  • 主配置文件:nginx .conf

  • 子配置文件: include conf.d/*.conf

  • fastcgi, uwsgi,scgi 等协议相关的配置文件

  • mime.types:支持的mime类型,MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型,MIME消息能包含文本、图像、音频、视频以及其他应用程序专用的数据,是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。
    MIME参考文档:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME Types

nginx 配置文件格式说明

配置文件由指令与指令块构成每条指令以;分号结尾,指令与值之间以空格符号分隔可以将多条指令放在同一行,用分号分隔即可,但可读性差,不推荐指令块以{ }大括号将多条指令组织在一起,且可以嵌套指令块include语句允许组合多个配置文件以提升可维护性使用#符号添加注释,提高可读性使用$符号使用变量部分指令的参数支持正则表达式

Nginx 主配置文件的配置指令方式:

directive value [value2 ...];注意(1) 指令必须以分号结尾(2) 支持使用配置变量 内建变量:由Nginx模块引入,可直接引用 自定义变量:由用户使用set命令定义,格式: set variable_name value; 引用变量:$variable_name

主配置文件结构:四部分

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

全局语句块

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

默认的nginx.conf 配置文件格式说明

#全局配置端,对全局生效,主要设置nginx的启动用户/组,启动的工作进程数量,工作模式,NginxPID路径,日志路径等。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 (快速拷贝到kernelsocket buffer) >>协议栈。   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}

3.2全局配置

Main 全局配置段常见的配置指令分类

  • 正常运行必备的配置
  • 优化性能相关的配置
  • 用于调试及定位问题相关的配置
  • 事件驱动相关的配置

全局配置说明:

user nginx nginx; #启动Nginx工作进程的用户和组worker_processes [number | auto]; #启动Nginx工作进程的数量,一般设为和CPU核心数相同worker_cpu_affinity 00000001 00000010 00000100 00001000 | auto ; #将Nginx工作进程绑 affinity亲密关系定到指定的CPU核心,默认Nginx是不进行进程绑定的,绑定并不是意味着当前nginx进程独占以一核心CPU,但是可以保证此进程不会运行在其他核心上,这就极大减少了nginx的工作进程在不同的cpu核心上的来回跳转,减少了CPU对进程的资源分配与回收以及内存管理等,因此可以有效的提升nginx服务器的性能。CPU MASK: 00000001:0号CPU          00000010:1号CPU  10000000:7号CPU#示例:worker_cpu_affinity 0001 0010 0100 1000;第0号---第3号CPUworker_cpu_affinity 0101 1010; #示例worker_processes  4;worker_cpu_affinity 00000010 00001000 00100000 10000000;[root@centos8 ~]# ps axo pid,cmd,psr | grep nginx31093 nginx: master process /apps   134474 nginx: worker process         134475 nginx: worker process         334476 nginx: worker process         534477 nginx: worker process         735751 grep nginx#auto 绑定CPU#The special value auto (1.9.10) allows binding worker processes automatically to available CPUs:worker_processes auto; worker_cpu_affinity auto;#The optional mask parameter can be used to limit the CPUs available for automatic binding:worker_cpu_affinity auto 01010101;#错误日志记录配置,语法:error_log file [debug | info | notice | warn | error | crit | alert | emerg]#error_log logs/error.log;#error_log logs/error.log notice;error_log /apps/nginx/logs/error.log error; #pid文件保存路径pid       /apps/nginx/logs/nginx.pid;worker_priority 0; #工作进程优先级,-20~20(19)worker_rlimit_nofile 65536; #所有worker进程能打开的文件数量上限,包括:Nginx的所有连接(例如与代理服务器的连接等),而不仅仅是与客户端的连接,另一个考虑因素是实际的并发连接数不能超过系统级别的最大打开文件数的限制.最好与ulimit -n 或者limits.conf的值保持一致,daemon off;  #前台运行Nginx服务用于测试、docker等环境。master_process off|on; #是否开启Nginx的master-worker工作模式,仅用于开发调试场景,默认为onevents {   worker_connections  65536;  #设置单个工作进程的最大并发连接数   use epoll; #使用epoll事件驱动,Nginx支持众多的事件驱动,比如:select、poll、epoll,只能设置在events模块中设置。   accept_mutex on; #on为同一时刻一个请求轮流由work进程处理,而防止被同时唤醒所有worker,避免多个睡眠进程被唤醒的设置,默认为off,新请求会唤醒所有worker进程,此过程也称为"惊群",因此nginx刚安装完以后要进行适当的优化。建议设置为on   multi_accept on; #on时Nginx服务器的每个工作进程可以同时接受多个新的网络连接,此指令默认为off,即默认为一个工作进程只能一次接受一个新的网络连接,打开后几个同时接受多个。建议设置为on}

范例: 实现 nginx 的高并发配置

[root@centos7 ~]#ulimit -n 102400[root@centos7 ~]#while true;do ab -c 5000 -n 10000 http://10.0.0.8/;sleep 0.5;done#默认配置不支持高并发,会出现以下错误日志[root@centos8 conf]#tail /apps/nginx/logs/error.log2020/09/24 21:19:33 [crit] 41006#0: *1105860 open() "/apps/nginx/html/50x.html" failed (24: Too many open files), client: 10.0.0.7, server: localhost, request: "GET / HTTP/1.0", host: "10.0.0.8"2020/09/24 21:19:33 [crit] 41006#0: accept4() failed (24: Too many open files)2020/09/24 21:19:33 [crit] 41006#0: *1114177 open() "/apps/nginx/html/index.html" failed (24: Too many open files), client: 10.0.0.7, server: localhost, request: "GET / HTTP/1.0", host: "10.0.0.8"#如果systemd启动,则需要修改nginx.service文件中加LimitNOFILE=100000,才能有效#如果非systemd启动,可以修改下面pam限制[root@centos8 ~]#vim /etc/security/limits.conf *               soft   nofile          1000000*               hard   nofile          1000000[root@centos8 ~]#vim /apps/nginx/conf/nginx.confworker_rlimit_nofile 100000; [root@centos8 ~]#systemctl restart nginx[root@centos8 ~]# watch -n1 'ps -axo pid,cmd,nice | grep nginx #验证进程优先级

3.3 http 配置块

http 协议相关的配置结构

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

work processes

image-20211209092039764

查看进程与cpu的关系

image-20211209092823769

面试:你是如何优化nginx性能

亲缘性

image-20211209102735362

image-20211209102751120

image-20211209102804301

nginx docker filezhongjia

image-20211209100330509

image-20211209100412675

3.3 http语句块

http 协议相关的配置结构:一个serve块就是一个虚拟主及

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

http 协议配置说明

3.3.1 MIME

3.4 核心配置示例

基于不同的IP、不同的端口以及不用得域名实现不同的虚拟主机,依赖于核心模块

ngx_http_core_module实现。

3.4.1 新建一个 PC web 站点

3.4.4 location 的详细使用

在一个server中location配置段可存在多个,用于实现从uri到文件系统的路径映射;ngnix会根据用户请求的URI来检查定义的所有location,按一定的优先级找出一个最佳匹配,而后应用其配置在没有使用正则表达式的时候,nginx会先在server中的多个location选取匹配度最高的一个uri,uri是用户请求的字符串,即域名后面的web文件路径,然后使用该location模块中的正则url和字符串,如果匹配成功就结束搜索,并使用此location处理此请求。

location 官方帮助:

#location语法规则lication [=|~|~*|^~]uri{...}=   #用于标准uri前,需要请求字串与uri精确匹配,大小敏感,如果匹配成功就停止向下匹配并立即处理请求^~  #用于标准uri前,表示包含正则表达式,并且匹配以指定的正则表达式开头,对uri的最左边部分做匹配检查,不区分字符大小写~   #用于标准uri前,表示包含正则表达式,并且区分大小写~*  #用于标准uri前,表示包含正则表达式,并且不区分大写不带符号 #匹配起始于此uri的所有的uri\   #用于标准uri前,表示包含正则表达式并且转义字符。可以将 . * ?等转义为普通符号#匹配优先级从高到低:=, ^~, ~/~*, 不带符号

符号优先级问题

image-20211209113557666

4.3NGINX变量

nginx的变量可以在配置文件中引用,作为功能判断或者日志等场景使用

变量可以分为内置变量和自定义变量

内置变量是由nginx模块自带,通过变量可以获取到众多的与客户端访问相关的值。

4.3.1 内置变量

官方文档

http://nginx.org/en/docs/varindex.html

常用内置变量

$remote_addr; #存放了客户端的地址,注意是客户端的公网IP$proxy_add_x_forwarded_for#此变量表示将客户端IP追加请求报文中X-Forwarded-For首部字段,多个IP之间用逗号分隔,如果请求中没有X-Forwarded-For,就使用$remote_addrthe “X-Forwarded-For” client request header field with the $remote_addr variable appended to it, separated by a comma. If the “X-Forwarded-For” field is not present in the client request header, the $proxy_add_x_forwarded_for variable is equal to the $remote_addr variable.$args; #变量中存放了URL中的所有参数,例如:http://www.magedu.org/main/index.do?id=20190221&partner=search#返回结果为: id=20190221&partner=search$is_args#如果有参数为? 否则为空“?” if a request line has arguments, or an empty string otherwise$document_root; #保存了针对当前资源的请求的系统根目录,例如:/apps/nginx/html$document_uri;#保存了当前请求中不包含参数的URI,注意是不包含请求的指令,比如:http://www.magedu.org/main/index.do?id=20190221&partner=search会被定义为/main/index.do #返回结果为:/main/index.do$host; #存放了请求的host名称limit_rate 10240;echo $limit_rate;#如果nginx服务器使用limit_rate配置了显示网络速率,则会显示,如果没有设置, 则显示0$remote_port;#客户端请求Nginx服务器时随机打开的端口,这是每个客户端自己的端口$remote_user;#已经经过Auth Basic Module验证的用户名$request_body_file;#做反向代理时发给后端服务器的本地资源的名称$request_method;#请求资源的方式,GET/PUT/DELETE等$request_filename;#当前请求的资源文件的磁盘路径,由root或alias指令与URI请求生成的文件绝对路径,如:/apps/nginx/html/main/index.html$request_uri;#包含请求参数的原始URI,不包含主机名,相当于:$document_uri?$args,例如:/main/index.do?id=20190221&partner=search $scheme;#请求的协议,例如:http,https,ftp等$server_protocol;#保存了客户端请求资源使用的协议的版本,例如:HTTP/1.0,HTTP/1.1,HTTP/2.0等$server_addr;#保存了服务器的IP地址$server_name;#请求的服务器的主机名$server_port;#请求的服务器的端口号$http_user_agent;#客户端浏览器的详细信息$http_cookie;#客户端的所有cookie信息$cookie_<name>#name为任意请求报文首部字部cookie的key名$http_<name>#name为任意请求报文首部字段,表示记录请求报文的首部字段,ame的对应的首部字段名需要为小写,如果有横线需要替换为下划线arbitrary request header field; the last part of a variable name is the field name converted to lower case with dashes replaced by underscores #用下划线代替横线#示例: echo $http_user_agent; echo $http_host;$sent_http_<name>#name为响应报文的首部字段,name的对应的首部字段名需要为小写,如果有横线需要替换为下划线,此变量有问题echo $sent_http_server;$arg_<name>#此变量存放了URL中的指定参数,name为请求url中指定的参数#示例: echo $http_user_agent; echo $http_host;$sent_http_<name>#name为响应报文的首部字段,name的对应的首部字段名需要为小写,如果有横线需要替换为下划线,此变量有问题echo $sent_http_server;$arg_<name>#此变量存放了URL中的指定参数,name为请求url中指定的参数

范例:

[root@centos8 ~]#vi /apps/nginx/conf/conf.d/pc.conf location /main {     index index.html;     default_type text/html;     echo "hello world,main-->";     echo $remote_addr ;     echo $args ;     echo $document_root;     echo $document_uri;     echo $host;     echo $http_user_agent;     echo $http_cookie;     echo $request_filename;     echo $scheme;     echo $scheme://$host$document_uri?$args;  }     [root@centos6 ~]#curl -b title=ceo 'http://www.magedu.org/main/index.do?id=20190221&partner=search'hello world,main-->10.0.0.6id=20190221&partner=search/apps/nginx/html/main/index.dowww.magedu.orgcurl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3 libidn/1.18 libssh2/1.4.2title=ceo/apps/nginx/html/main/index.dohttp

4.3.2 自定义变量

4.4 Nginx 自定义访问日志

格式语法:

Syntax: access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];access_log off; #关闭访问日志Default: access_log logs/access.log combined;Context: http, server, location, if in location, limit_except

4.4.1 自定义默认格式日志

如果是要保留日志的源格式,只是添加相应的日志内容,则配置如下:

4.4.3 json 格式的日志访问统计

4.5 Nginx 压缩功能(常用 )

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

Nginx对文件的压缩功能是依赖于模块 ngx_http_gzip_module,默认是内置模块

4.6https功能

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

image-20211209172722212

https 实现过程如下:1.客户端发起HTTPS请求:客户端访问某个web端的https地址,一般都是443端口2.服务端的配置:采用https协议的服务器必须要有一套证书,可以通过一些组织申请,也可以自己制作,目前国内很多网站都自己做的,当你访问一个网站的时候提示证书不可信任就表示证书是自己做的,证书就是一个公钥和私钥匙,就像一把锁和钥匙,正常情况下只有你的钥匙可以打开你的锁,你可以把这个送给别人让他锁住一个箱子,里面放满了钱或秘密,别人不知道里面放了什么而且别人也打不开,只有你的钥匙是可以打开的。3.传送证书:服务端给客户端传递证书,其实就是公钥,里面包含了很多信息,例如证书得到颁发机构、过期时间等等。4.客户端解析证书:这部分工作是有客户端完成的,首先回验证公钥的有效性,比如颁发机构、过期时间等等,如果发现异常则会弹出一个警告框提示证书可能存在问题,如果证书没有问题就生成一个随机值,然后用证书对该随机值进行加密,就像2步骤所说把随机值锁起来,不让别人看到。5.传送4步骤的加密数据:就是将用证书加密后的随机值传递给服务器,目的就是为了让服务器得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值进行加密解密了。6.服务端解密信息:服务端用私钥解密5步骤加密后的随机值之后,得到了客户端传过来的随机值(私钥),然后把内容通过该值进行对称加密,对称加密就是将信息和私钥通过算法混合在一起,这样除非你知道私钥,不然是无法获取其内部的内容,而正好客户端和服务端都知道这个私钥,所以只要机密算法够复杂就可以保证数据的安全性。7.传输加密后的信息:服务端将用私钥加密后的数据传递给客户端,在客户端可以被还原出原数据内容。8.客户端解密信息:客户端用之前生成的私钥获解密服务端传递过来的数据,由于数据一直是加密的,因此即使第三方获取到数据也无法知道其详细内容。

4.6.1 https 配置参数

nginx 的https 功能基于模块ngx_http_ssl_module实现,因此如果是编译安装的nginx要使用参数ngx_http_ssl_module开启ssl功能,但是作为nginx的核心功能,yum安装的nginx默认就是开启的,编
译安装的nginx需要指定编译参数--with-http_ssl_module开启

posted @   爬上山丘  阅读(161)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
点击右上角即可分享
微信分享提示