Nginx 架构分析

lance 2020-04-03 PM 166℃ 0条

Nginx 模块化介绍

  • Nginx 基于模块化设计,每个模块是一个功能实现,分布式开发,团队合作
  • 核心模块,标准 HTTP 模块,可选 HTTP 模块,邮件模块,第三方模块
  • 编译后的源码目录 objs/ngx_modules.c

Nginx 模块化结构

Nginx 涉及到的模块分为核心模块、标准 HTTP 模块、可选 HTTP 模块、邮件服务模块以及第三方模块等五大类。
 
53409-y3edoa5ih6g.png

核心模块

核心模块是指 Nginx 服务器正常运行时必不可少的模块,它们提供了 Nginx 最基本最核心的服务,如进程管理、权限控制、错误日志记录等。
主要包含对两类功能的支持,一类是主体功能,包括进程管理、权限控制、错误日志记录、配置解析等,
另一类是用于响应请求事件必需的功能,包括事件驱动机制、正则表达式解析等。

ngx_core_module
ngx_errlog_module
ngx_conf_module
ngx_regex_module
ngx_events_module
ngx_event_core_module
ngx_epoll_module

标准HTTP模块

标准 HTTP 模块是编译 Nginx 后包含的模块,其支持 Nginx 服务器的标准 HTTP 功能。

模块 功能
ngx_http_core 配置端口,URI 分析,服务器响应错误处理,别名控制以及其他 HTTP 核心事务
ngx_http_access_module 基于 IP 地址的访问控制(允许/拒绝)
ngx_http_auth_basic_module 基于 HTTP 的身份认证
ngx_http_autoindex_module 处理以 “/” 结尾的请求并自动生成目录列表
ngx_http_browser_module 解析HTTP请求头中的“User-Agent”域的值
ngx_http_charset_module 指定网页编码
ngx_http_empty_gif_module 从内存创建一个 1 x 1 的透明 gif 图片,可以快速调用
ngx_http_fastcgi_module 对 FastCGI 的支持
ngx_http_geo_module 将客户端的 IP 转化为键值对变量,该模块主要用来针对客户的的 IP 来定义变量
ngx_http_gzip_module 压缩请求响应,可以减少数据传输
ngx_http_headers_filter_module 设置 HTTP 响应头
ngx_http_index_module 处理以 “/” 结尾的请求,如果没有找到该目录下的 index 页,就将请求转给 ngx_http_autoindex_module 模块处理
ngx_http_limit_req_module 限制来自客户端的请求的响应和处理速率
ngx_http_limit_conn_module 限制来自客户端的连接的响应和处理速率
ngx_http_log_module 自定义 access 日志
ngx_http_map_module 创建任意键值对变量
ngx_http_memcached_module 对 Memcached 的支持
ngx_http_proxy_module 支持代理事务
ngx_http_referer_module 对 HTTP 头中的 "referer" 进行过滤处理,比如,实现防盗链功能
ngx_http_rewrite_module 实现 nginx 的 rewrite 功能
ngx_http_scgi_module 对 SCGI 的支持
ngx_http_upstream_module 定义一组服务器,可以接收来自代理、Fastcgi、Memcached 的中重定向,主要用于负载均衡

可选 HTTP 模块

可选 HTTP 模块主要用于扩展标准的 HTTP 功能,使其能够处理一些特殊的 HTTP 请求。在编译 Nginx 时,如果不指定这些模块,默认是不会安装的。

模块 功能
ngx_http_addition_module 在响应请求的页面开始或者结尾添加文本信息
ngx_http_degradation_module 在低内存的情形下允许 Nginx 服务器返回 444 错误或 204 错误
ngx_http_perl_module 在 Nginx 的配置文件中可以使用 Perl 脚本
ngx_http_flv_module 支持将 Flash 多媒体信息按照流文件传输,可以根据客户端指定的开始位置返回 Flash
ngx_http_geoip_module 支持解析基于 GeoIP 数据库的客户端请求
ngx_google_perflools_module 支持 Google Performance Tools 的一套用于 C++Profile 的工具集
ngx_http_image_filter_module 支持将 H.264/AAC 编码的多媒体信息(后缀名通常为 mp4、m4v 或 m4a)按照流文件传输,常与 ngx_http_flv_module 模块一起使用
ngx_http_random_index_module Nginx 接收到以 “/” 结尾的请求时,在对应的目录下随机选择一个文件作为 index 文件
ngx_http_secure_link_module 支持对请求链接的有效性检查
ngx_http_ssl_module 对 HTTPS/SSL 支持
ngx_http_stub_status_module 支持返回 Nginx 服务器的统计信息,一般包括处理连接的数量、连接成功的数量、处理的请求数、读取和返回的 Header 信息数等信息
ngx_http_sub_module 使用指定的字符串替换响应信息中的信息
ngx_http_dav_module 支持 HTTP 协议和 WebDAV 协议中 PUT、DELETE、MKCOL、COPY 和 MOVE 方法
ngx_http_xslt_module 将 XML 响应信息使用 XSLT(拓展样式表转换语言)进行转换

邮件服务模块

主要用于支持 Ningx 的邮件服务。

第三方模块

并非有 Nginx 官方提供,而是由第三方机构或者个人开发的模块,用于实现某种特殊功能。
echo-nginx-module 支持在 Nginx 配置文件中使用 echo、sleep、time 以及 exec 等类 shell 命令
lua-nginx-module 使 Nginx 支持 lua 脚本语言


Nginx 的 web 请求机制

  • 并行处理:多进程,多线程,异步
     
    35281-bfm29mvvh07.png

同步机制

同步、异步发生在当客户端发起请求后,服务端处理客户端的请求时。
同步机制,是指客户端发送请求后,需要等待服务端(内核)返回信息后,再继续发送下一个请求。
在同步机制中,所有的请求在服务器端得到同步,即发送方和接收方对请求的处理步调是一致的。

异步机制

异步机制,是指客户端发出一个请求后,不等待服务端(内核)返回信息,就继续发送下一个请求。
在异步机制中,所有来自发送方的请求形成一个队列,接收方处理完后再通知发送方。

举例:一家酒店前台,在旺季的高峰时间段会接很多预定酒席的电话。
如果是同步机制情况下,前台每接一个电话后先不挂掉电话,而是去查询有无剩余酒席,查到结果后,告诉客户。
如果是异步机制情况下,前台每接一个预定电话直接回复客户,一会回复,此时前台把查询这件事情交给了另外的同事,
该前台挂掉电话后,继续处理其他客户的事情,当另外的同事查询到结果后再通知给前台,前台再通知客户。

阻塞

阻塞与非阻塞发生在 IO 调度中,比如内核到磁盘 IO。
阻塞方式下,进程/线程在获取最终结果之前,被系统挂起了,也就是所谓的阻塞了,在阻塞过程中该进程什么都干不了,
直到最终结果反馈给它时,它才恢复运行状态。

非阻塞

非阻塞方式和阻塞相反,进程/线程在获取最终结果之前,并没有进入被挂起的状态,而是该进程可以继续执行新的任务。
当有最终结果反馈给该进程时,它再把结果交给客户端。

举例:依然是酒店前台接待预定酒席电话的案例。
此时角色不再是前台,而是她的查询有无剩余酒席的同事。如果是阻塞方式,该同事在查询有无剩余酒席的过程中,需要傻傻地
等待酒店管理系统给他返回结果,在此期间不能做其他事情。
如果是非阻塞,该同事在等待酒店管理系统给他返回结果这段时间,可以做其他事情,比如可以通知前台剩余酒席的情况。

Nginx 的请求机制

Nginx 之所以可以支持高并发,是因为 Nginx 用的是异步非阻塞的机制,而 Nginx 是靠事件驱动模型来实现这种机制的。

在 Nginx 的事件驱动模型下,客户端发起的所有请求在服务端都会被标记为一个事件,Nginx 会把这些事件收集到“事件收集器”里,
然后再把这些事件交给内核去处理。

Nginx 事件驱动模型

事件驱动模型

事件驱动模型是实现异步非阻塞的一个手段。事件驱动模型中,一个进程(线程)就可以了。

对于 web 服务器来说,客户端 A 的请求连接到服务端时,服务端的某个进程(Nginx worker process)会处理该请求,
此进程在没有返回给客户端 A 结果时,它又去处理了客户端 B 的请求。
服务端把客户端A以及客户端 B 发来的请求作为事件交给了 “事件收集器”,
而 “事件收集器” 再把收集到的事件交由 “事件发送器” 发送给 “事件处理器” 进行处理。
最后 “事件处理器” 处理完该事件后,通知服务端进程,服务端进程再把结果返回给客户端 A、客户端 B。

在这个过程中,服务端进程做的事情属于用户级别的,而事件处理这部分工作属于内核级别的。
也就是说这个事件驱动模型是需要操作系统内核来作为支撑的。

Nginx 的事件驱动模型

 
70110-71pz2dp28aq.png
 

Nginx 的事件驱动模型,支持 select、poll、epoll、rtsig、kqueue、/dev/poll、eventport 等。
最常用的是前三种,其中 kqueue 模型用于支持 BSD 系列平台的事件驱动模型。kqueue 是 poll 模型的一个变种,本质上和 epoll 一样。
/dev/poll 是 Unix 平台的事件驱动模型,其主要在 Solaris7 及以上版本、HP/UX11.22 及以上版本、IRIX6.5.15 及以上版本、
Tru64 Unix 5.1A 及以上版本的平台使用。
eventport 是用于支持 Solaris10 及以上版本的事件驱动模型。

select 模型

Linux 和 Windows 都支持,使用 select 模型的步骤是:

1. 创建所关注事件的描述符集合,对于一个描述符,可以关注其上面的 读(Read)事件、写(Write)事件 以及 异常发生(Exception)事件。
在 select 模型中,要创建这 3 类事件描述符集合。
2. 调用底层提供的 select() 函数,等待事件发生。
3. 轮询所有事件描述符集合中的每一个事件描述符,检查是否有相应的事件发生,如果有就进行处理。

poll 模型

poll 模型是 Linux 平台上的事件驱动模型,在 Linux2.1.23 中引入的,Windows 平台不支持该模型。
poll 模型和 select 模型工作方式基本相同,区别在于,select 模型创建了 3 个描述符集合,而 poll 模型只创建一个描述符集合。

epoll 模型

epoll 模型属于 poll 模型的变种,在 Linux2.5.44 中引入。epoll 比 poll 更加高效,原因在于它不需要轮询整个描述符集合,
而是 Linux 内核会关注事件集合,当有变动时,内核会发来通知。

设计架构概览

  • Nginx 基于模块化设计,基于事件驱动模型处理请求/主进程/工作进程

Nginx 架构

Nginx 服务器使用 master/worker 多进程模式。
主进程(Master process) 启动后,会接收和处理外部信号;
主进程启动后通过 fork() 函数产生一个或多个 子进程(work process),每个子进程会进行进程初始化、
模块调用以及对事件的接收和处理等工作。
 
83844-j8qf2sbk8bn.png

主进程

主要功能是和外界通信和对内部其他进程进行管理,具体来说有以下几点:

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

子进程(worker process)

是由主进程生成,生成数量可以在配置文件中定义。该进程主要工作有:

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

73608-ft1j0tcb2e8.png


标签: linux, nginx

非特殊说明,本博所有文章均为博主原创。

觉得文章不错,打赏一点吧,1分也是爱😀

WeChat Pay

微信打赏

Alipay

支付宝打赏

评论啦~