nginx原理深入

nginx原理深入

参考:https://blog.csdn.net/Vivid_110/article/details/50658422

目录

1. nginx架构是怎样的?

2. nginx请求流程是怎样的?

3. nginx网络模型是什么样的?

4. nginx实现高并发的原理?

5. nginx和Apache、tomcat的区别


1. nginx架构

nginx基于事件驱动,采用多进程单线程模式的非阻塞架构。大量使用多路复用和事件通知,并且给不同的进程分配不同的任务。数量有限的工作进程(Worker)使用高效的单线程循环处理连接,每个worker进程每秒可以处理数千个并发连接、请求(思考这样可能有什么坏处),nginx采用Master/worker工作模式,主进程启动后会接收和处理外部信号,主进程启动后通过fork() 函数产生一个或多个子进程(work process),每个子进程会进行进程初始化,master进程和worker进程之间采用信号通信。

主进程(Master)

主要功能是和外部通信和管理内部进程

  • 读取Nginx配置文件并验证有效性
  • 建立、绑定和关闭socket
  • 按照配置生成、管理工作进程
  • 日志文件管理
  • 接收外界指令,比如重启、关闭、重载服务等指令

子进程(worker)

由主进程生成,生成数量可以自己定义,一般为CPU核数

  • 接收客户端请求
  • 将请求依次送入各个功能模块进行过滤处理
  • IO调用,获取响应数据
  • 与后端服务器通信,接收后端服务器处理结果
  • 数据缓存,访问缓存索引,查询和调用缓存数据
  • 发送请求结果,响应客户端请求
  • 接收主进程指令,如重启、重载、退出等

nginx架构

模块划分

网上模块划分有很多种,比较靠谱的是划分为核心模块和其他功能模块。在两者之间又有HTTP模块和mail模块对应用层不同协议做进一步的封装。其他功能模块包括:事件模块、阶段处理器、输出过滤器、变量处理器、协议模块、上游和负载均衡模块。模块之间链接成流水线,每个模块对请求做一定的加工。

2. nginx请求流程是怎样的?

一个典型的请求流程:

  1. 客户端发送HTTP请求。
  2. nginx核心模块从配置文件查找匹配该请求的位置,根据这个位置选择适当的阶段处理器。
  3. 如果配置为反向代理,负载均衡器挑选一个上游服务器用于转发请求。
  4. 阶段处理器完成工作,传递到过滤器链逐级过滤。
  5. 最终响应客户端请求

请求过程中模块调用的顺序:

worker中使用IO多路复用机制监听事件的到来,当nginx处理一个http请求时会经过多个阶段处理器。阶段处理器一般做这样几件事情:获取location配置,产生适当的响应,发送响应头,发送响应体。处理器函数有一个参数:描述请求的结构体。请求结构体有许多关于客户端请求的有用信息,例如:请求方法类型,URI和请求头等。然后此时会交由内容处理器返回匹配的内容,如某个静态文件。内容处理器产生的内容不会直接返回,
而是继续交给过滤器模块处理,过滤器也同location相关,一个location可配置多个过滤器,过滤器加工处理器产生输出。过滤器有header filter和body filter。

header filter有三个步骤:

  1. 决定是否处理这个响应
  2. 处理响应
  3. 调用下一个过滤器

body filter转换所生成的内容:

  1. SSI
  2. XSLT过滤
  3. 图片过滤
  4. 字符集转换
  5. Gzip压缩
  6. Chunked编码

经过过滤器链之后,请求被发到writer,有两个额外的具有特定功能的过滤器与writer相关,copy filter和postpone filter。Copy filter负责将相关的响应内容填充到内存缓冲区,这些响应内容有可能存储在反向代理的临时目录,Postpone filter用于子请求处理。

子请求是一个处理请求、响应很重要的机制,同时也是nginx最强大的功能之一。通过子请求,Nginx可以返回另一个URL的响应,这个URL与客户端最初请求的URL不同。一些web框架称之为内部跳转,但nginx功能更强,不仅能运行多个子请求并将这些子请求的响应合并成一个,而且还能嵌套和分级。子请求可以产生子-子请求,子-子请求能产生子-子-子请求。子请求可以映射到磁盘文件,其他处理,或者上游服务器。子请求在根据原始响应数据插入附加内容时很有用。例如,SSI模块使用一个过滤器解析返回文档的内容,然后用指定URL的内容来替换include指令。或者做一个过滤器,能够在一个URL产生的响应内容之后附加一些新的文档内容。

3. nginx网络模型是什么样的?

参考:https://fankeke.github.io/2017/03/09/Nginx%E7%9A%84%E7%BD%91%E7%BB%9C%E6%A8%A1%E5%9E%8B-%E6%BC%94%E5%8F%98/

参考文章对于nginx网络模型的描述已经足够到位了,这里不再重复劳动,只是捡重点说下面试的时候如何表达这一块的内容。

1. 什么是惊群现象?

惊群现象说的是如果有请求来临,内核会唤醒所有的进程。传统的Apache服务采用为每个请求分发一个线程来处理,而nginx采用IO多路复用机制由监听的事件驱动。所以在没有其它手段的情况下, 每当有请求来临,所有的work进程都会被唤醒,造成了无用唤醒,浪费了资源。

2. nginx如何解决惊群现象?

nginx通过开启accept_mutex指令来解决惊群现象,具体描述就是开启了该指令后,每个work进程不会直接把监听套接字加入自己的epoll中,而是去竞争一把自旋锁,只有拿到锁的进程才能做上述操作,而没有拿到锁的进程就会删除自己的epoll中监听的套接字,这样当有新的请求来临时,只会有一个worker进程去处理请求。

1,在请求量不是特别大的情况下,Nginx这种解决惊群现象的手段提升了网络服务质量,避免多个进程无谓的被“唤醒”去accept请求失败而导致的损耗。
2,然后现在在很多情况下证明:当并发请求量过大时,这种依靠抢锁机制解决惊群的手段,会导致处理请求的效率下降,所以现在较多的建议是关闭accept_mutux锁,让Nginx不解决惊群。

3. 使用reuseport更好的解决惊群现象

使用方法

使用只需在监听的端口后加上reuserport参数即可

server {
    #使用reuserport解决惊群效应
    listen 80 reuseport;
    server_name localhost;
    ..
}

原理简单描述

master进程在创建worker进程之前就会对使用reuseport的端口创建worker进程个数那么多的监听套接字,那么fork出来的worker进程同样也会有那么多的监听套接字,由内核决定哪个进程监听哪个端口。

4. nginx实现高并发的原理

  • 多进程单线程模式:Apache的多线程模式会为每个进来的请求创建一个独立的线程去处理,当有几千个请求过来的时候就会创建几千个线程,操作系统切换线程时产生的资源代价非常的高。而nginx使用多进程+单线程的模式不会有线程的上下文切换,每个进程使用IO多路复用机制接收事件处理请求,非常的高效。

5. nginx、tomcat、apache的区别

nginx与apache的区别

  • nginx是异步的,apache是同步多进程;
  • nginx比apache占用更少的资源;
  • nginx比apache配置更简单;

tomcat与nginx、apache的区别

  • nginx和apache处理静态资源,tomcat处理动态资源;
  • nginx/apache是一个http server,而tomcat是一个application server,其实质是一个Servlet/jsp容器