nginx原理深入
目录
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调用,获取响应数据
- 与后端服务器通信,接收后端服务器处理结果
- 数据缓存,访问缓存索引,查询和调用缓存数据
- 发送请求结果,响应客户端请求
- 接收主进程指令,如重启、重载、退出等

模块划分
网上模块划分有很多种,比较靠谱的是划分为核心模块和其他功能模块。在两者之间又有HTTP模块和mail模块对应用层不同协议做进一步的封装。其他功能模块包括:事件模块、阶段处理器、输出过滤器、变量处理器、协议模块、上游和负载均衡模块。模块之间链接成流水线,每个模块对请求做一定的加工。
2. nginx请求流程是怎样的?
一个典型的请求流程:
- 客户端发送HTTP请求。
- nginx核心模块从配置文件查找匹配该请求的位置,根据这个位置选择适当的阶段处理器。
- 如果配置为反向代理,负载均衡器挑选一个上游服务器用于转发请求。
- 阶段处理器完成工作,传递到过滤器链逐级过滤。
- 最终响应客户端请求
请求过程中模块调用的顺序:
worker中使用IO多路复用机制监听事件的到来,当nginx处理一个http请求时会经过多个阶段处理器。阶段处理器一般做这样几件事情:获取location配置,产生适当的响应,发送响应头,发送响应体。处理器函数有一个参数:描述请求的结构体。请求结构体有许多关于客户端请求的有用信息,例如:请求方法类型,URI和请求头等。然后此时会交由内容处理器返回匹配的内容,如某个静态文件。内容处理器产生的内容不会直接返回,
而是继续交给过滤器模块处理,过滤器也同location相关,一个location可配置多个过滤器,过滤器加工处理器产生输出。过滤器有header filter和body filter。
header filter有三个步骤:
- 决定是否处理这个响应
- 处理响应
- 调用下一个过滤器
body filter转换所生成的内容:
- SSI
- XSLT过滤
- 图片过滤
- 字符集转换
- Gzip压缩
- Chunked编码
经过过滤器链之后,请求被发到writer,有两个额外的具有特定功能的过滤器与writer相关,copy filter和postpone filter。Copy filter负责将相关的响应内容填充到内存缓冲区,这些响应内容有可能存储在反向代理的临时目录,Postpone filter用于子请求处理。
子请求是一个处理请求、响应很重要的机制,同时也是nginx最强大的功能之一。通过子请求,Nginx可以返回另一个URL的响应,这个URL与客户端最初请求的URL不同。一些web框架称之为内部跳转,但nginx功能更强,不仅能运行多个子请求并将这些子请求的响应合并成一个,而且还能嵌套和分级。子请求可以产生子-子请求,子-子请求能产生子-子-子请求。子请求可以映射到磁盘文件,其他处理,或者上游服务器。子请求在根据原始响应数据插入附加内容时很有用。例如,SSI模块使用一个过滤器解析返回文档的内容,然后用指定URL的内容来替换include指令。或者做一个过滤器,能够在一个URL产生的响应内容之后附加一些新的文档内容。
3. nginx网络模型是什么样的?
参考文章对于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容器