目录

NGINX源码阅读

NGINX源码阅读指南

一、前言

  • 源码版本:2018-10-02 nginx-1.15.5
  • 环境说明:主要描述Darwin环境下的流程,与Linux环境下类似,Win32环境下可能会减少部分流程
  • 运行模式
    • Darwin/Linux等*nix类系统使用多进程方式运行
    • Win32使用多线程方式运行
  • 命名规范ngx_开头的变量多为全局变量
  • 模块命名ngx_model_name.c多为处理nginx配置中相应模块的配置处理,ngx_model_name_core_module.c多为该模块的核心(通用)处理逻辑

二、NGINX架构

1. 进程工作模式

1.1 多进程模式

  • master进程

    • 接收外部信号发送给worker进程(如stop、restart、reload等)
    • 监控worker进程运行状态,worker异常退出后重新启动新的worker进程
    • 缓存管理
  • worker进程

    • 处理基本网络事件,如http、mail请求等

1.2 单进程模式

  • 调试情况下使用,直接使用单进程处理网络事件

1.3 核心配置参数

配置项 配置块 值类型 默认值 说明
daemon main flag 1 是否使用守护进程模式开启服务
master_process main flag 1 是否开启master管理进程,主要用于nginx开发调试
timer_resolution main time 0 控制gettimeofday()系统调用时机
pid main string logs/nginx.pid 主进程pid的存放路径
lock_file main string logs/nginx.lock 用于不支持原子操作的系统使用文件锁
worker_processes main unit string(auto) 1
debug_points main uint 0 监测内部错误时中止或停止进程
user main string nobody 设置worker进程运行的用户和用户组
worker_priority main int 0 设置worker进程的调度优先级
worker_cpu_affinity main umask string(auto)
worker_rlimit_nofile main uint 修改worker进程的最大文件描述符限制
worker_rlimit_core main uint 修改worker进程的核心文件最大限制
worker_shutdown_timeout main time 0 设置worker进程的结束等待时间
working_directory main string 设置工作目录
env main string TZ 设置需要的环境变量
load_module main string 用于加载动态模块

2. 启动阶段

2.1 master处理流程

  1. 初始化阶段

    • 日志初始化(初始化日志格式,打开日志文件)
    • SSL初始化
    • 保存启动参数
    • 解析配置文件路径
    • 运行环境系统初始化(获取CPU缓存块大小、内存页大小、CPU核数)
  2. 配置加载阶段

    • 压缩表初始化
    • 模块预初始化(将所需加载的模块信息加入全局变量)
    • 轮训初始化(加载配置、加载模块、创建共享内存、关闭无用socket)
  3. 启动管理阶段

    • 检查配置文件错误
    • 处理外部信号
    • 注册信号处理器
    • 守护进程模式下fork子进程
    • 创建pid文件
    • 启动worker进程循环

2.2 worker处理流程

  1. 初始化

    • 设置进程执行优先级
    • 设置进程可打开的最大文件描述符
    • 根据nginx.conf设置进程运行的用户、用户组
    • 设置CPU亲缘性
    • 解除阻塞系统信号
    • 执行各模块init_process
    • 设置通道读事件回调
  2. 事件循环

    • 从定时事件红黑树中查找最近定时器
    • 检查worker是否繁忙,尝试获取事件监听锁
    • 等待I/O事件唤起
    • 处理accept事件
    • 释放事件监听锁
    • 处理时间到达的定时器
    • 处理普通事件
  3. 信号处理

    • ngx_exiting:检查定时器中是否仍有未处理事件
    • ngx_terminate:直接退出worker
    • ngx_quit:关闭定时器、socket监听、闲置连接
    • ngx_reopen:轮转日志

2.3 缓存管理处理流程

  • 设置进程类型为helper
  • 关闭socket监听
  • 重置最大连接数为512
  • 初始化(设置优先级、文件描述符、用户组等)
  • 设置定时器
  • 循环处理事件及定时器

3. 事件模块

3.1 加载流程

graph TD
    A[ngx_init_cycle] --> B[create_conf]
    A --> C[command->set]
    A --> D[init_conf]
    A --> E[init_module]
    F[ngx_event_process_init] --> G[init_event]
    F --> H[init_process]
    F --> I[add_event]
    F --> J[process_events]
    F --> K[event_handle]
    L[ngx_worker_process_exit] --> M[exit_process]
    N[ngx_master_process_exit] --> O[exit_master]

3.2 主要函数解析

事件结构
static ngx_event_module_t ngx_kqueue_module_ctx = {
    &kqueue_name,
    ngx_kqueue_create_conf,                /* create configuration */
    ngx_kqueue_init_conf,                  /* init configuration */

    {
        ngx_kqueue_add_event,              /* add an event */
        ngx_kqueue_del_event,              /* delete an event */
        ngx_kqueue_add_event,              /* enable an event */
        ngx_kqueue_del_event,              /* disable an event */
        NULL,                              /* add an connection */
        NULL,                              /* delete an connection */
#ifdef EVFILT_USER
        ngx_kqueue_notify,                 /* trigger a notify */
#else
        NULL,                              /* trigger a notify */
#endif
        ngx_kqueue_process_events,         /* process the events */
        ngx_kqueue_init,                   /* init the events */
        ngx_kqueue_done                    /* done the events */
    }
};
模块结构
ngx_module_t ngx_event_core_module = {
    NGX_MODULE_V1,
    &ngx_event_core_module_ctx,            /* module context */
    ngx_event_core_commands,               /* module directives */
    NGX_EVENT_MODULE,                      /* module type */
    NULL,                                  /* init master */
    ngx_event_module_init,                 /* init module */
    ngx_event_process_init,                /* init process */
    NULL,                                  /* init thread */
    NULL,                                  /* exit thread */
    NULL,                                  /* exit process */
    NULL,                                  /* exit master */
    NGX_MODULE_V1_PADDING
};
关键函数
函数 说明
ngx_event_module_init 检查文件描述符,分配共享内存
ngx_event_process_init 初始化连接池、事件定时器等
ngx_event_accept 处理accept事件,添加读事件
ngx_trylock_accept_mutex 尝试获取accept锁
ngx_event_connect_peer 连接上游服务
ngx_event_pipe 从上游读数据写入下游
ngx_event_pipe_read_upstream 读取上游数据
ngx_event_pipe_write_to_downstream 写入下游数据
ngx_event_recvmsg 处理UDP消息

3.3 事件配置

配置项 配置块 值类型 默认值 说明
worker_connections events uint 512 单worker可同时处理的最大连接数
use events string 根据系统选择 设置I/O事件通知机制
multi_accept events string off 是否尽可能多接收等待队列中的socket
accept_mutex events string off 是否开启accept互斥锁
accept_mutex_delay events uint 500 accept互斥锁延迟时间
debug_connection events string 开启debug日志的连接

三、HTTP服务

1. 初始化流程

create_main_conf
create_srv_conf
create_loc_conf
preconfiguration
init_main_conf
merge_srv_conf
merge_loc_conf
ngx_http_init_static_location_trees
ngx_http_init_phases
postconfiguration
ngx_http_optimize_servers

优化server信息列表

  • 添加各server所需地址的监听
  • 设置监听参数(backlog、reuseport等)
  • 将监听处理器设置为ngx_http_init_connection

2. 建立连接流程

  1. 查找请求对应的server配置
  2. 设置当前server的读控制器(ssl、http2、http)
  3. 如果读事件未就绪,将连接放回队列并添加读事件
  4. 如果读事件已就绪,执行对应读控制器

2.1 HTTPS处理流程

  1. 尝试从socket读取数据
  2. 创建ssl连接并完成握手
  3. 如果客户端使用http2,进入http2处理流程
  4. 否则进入http处理流程

2.2 HTTP2处理流程

  1. 发送http2的headers frame
  2. 设置单个stream的流量控制
  3. 接收客户端请求数据
  4. 处理HEADERS frame(检查错误、处理优先级等)
  5. 添加读事件
  6. 处理输出队列
  7. 处理已建立的连接

2.3 HTTP处理流程

  1. 读取socket中已接收信息
  2. 从复用连接池中移除当前连接
  3. 处理header相关信息
  4. 进入请求处理流程
  5. 添加输出写事件

3. 请求处理流程

NGINX采用阶段式处理请求,共8个阶段:

阶段 类型 说明 主要处理函数
POST_READ_PHASE 读取请求内容 获取客户端真实IP ngx_http_realip_handler
SERVER_REWRITE_PHASE server级别重写 重写URI ngx_http_rewrite_handler
FIND_CONFIG_PHASE 寻找location 查找匹配的location ngx_http_core_find_config_phase
REWRITE_PHASE location级别重写 重写URI ngx_http_rewrite_handler
POST_REWRITE_PHASE 重写后处理 检查URI重写结果 ngx_http_core_post_rewrite_phase
PREACCESS_PHASE 访问权限控制前 降级处理、连接限制 ngx_http_degradation_handler, ngx_http_limit_conn_handler
ACCESS_PHASE 访问权限控制 IP黑白名单、Basic认证 ngx_http_access_handler, ngx_http_auth_basic_handler
POST_ACCESS_PHASE 访问权限控制后 处理权限结果 ngx_http_core_post_access_phase
PRECONTENT_PHASE 内容生成前 请求镜像、文件检查 ngx_http_mirror_handler, ngx_http_try_files_handler
CONTENT_PHASE 内容生成 生成响应 ngx_http_core_content_phase, ngx_http_autoindex_handler
LOG_PHASE 日志记录 记录访问日志 ngx_http_log_handler

4. HTTP配置详解

4.1 核心配置参数

配置项 配置块 值类型 默认值 说明
variables_hash_max_size http uint 1024 变量哈希表最大大小
server_names_hash_max_size http uint 512 服务器名称哈希表最大大小
connection_pool_size http/server string 64*指针长度 每个连接的内存分配
request_pool_size http/server string 4096 每个请求的内存分配
client_header_timeout http/server time 60000 读取客户端请求头超时
client_header_buffer_size http/server string 1024 客户端请求头缓冲区大小
large_client_header_buffers http/server uint size 4 8192 大请求头缓冲区配置
keepalive_timeout http/server time 75000 长连接超时时间
keepalive_requests http/server uint 100 一个长连接的最大请求数

4.2 HTTP核心配置

配置项 配置块 值类型 默认值 说明
server http 配置块 设置虚拟服务器配置
location server 配置块 根据URI单独设置配置
listen http/server string *:80 设置监听地址
server_name http/server string "" 设置虚拟服务器名称
root http/server/location string {0, NULL} 设置请求根目录
alias location string 为特定location定义别名路径
limit_except location 配置块 为特定location增加请求方法限制
client_max_body_size http/server/location buf 110241024 客户端请求体最大大小
sendfile http/server/location flag 0 是否使用sendfile发送文件数据

5. HTTP状态码详解

状态码 类型 说明 适用场景
100 Continue 客户端应继续请求 未使用
101 Switching Protocols 服务器正在切换协议 proxy、uwsgi、scgi模块
200 OK 请求成功 常规响应
201 Created 资源已创建 WebDAV模块
204 No Content 请求成功但无内容 无内容响应
206 Partial Content 部分内容响应 Range请求
301 Moved Permanently 永久重定向 重定向
302 Moved Temporarily 临时重定向 重定向
304 Not Modified 内容未修改 缓存验证
400 Bad Request 语义有误 请求错误
401 Unauthorized 需要认证 认证失败
403 Forbidden 请求被拒绝 权限控制
404 Not Found 资源未找到 资源不存在
408 Request Timeout 请求超时 接收数据超时
409 Conflict 请求与当前状态冲突 WebDAV操作
413 Request Entity Too Large 请求体过大 请求体超过限制
414 Request URI Too Large 请求URI过长 URI过长
416 Range Not Satisfiable Range请求不合法 Range请求错误
429 Too Many Requests 请求过于频繁 速率限制
500 Internal Server Error 服务器内部错误 程序错误
502 Bad Gateway 网关错误 上游服务错误
503 Service Unavailable 服务不可用 限流、上游错误
504 Gateway Timeout 网关超时 上游响应超时

四、MAIL服务

1. 初始化流程

create_main_conf
create_srv_conf
init_main_conf
merge_srv_conf
ngx_mail_add_ports
ngx_mail_optimize_servers

优化监听列表

  • 如果相同端口有泛IP监听则忽略其他指定IP地址的监听
  • 添加各server所需地址的监听
  • 设置监听参数(backlog、rcvbuf等)
  • 将监听处理器设置为ngx_mail_init_connection

2. 建立连接流程

  1. 查找请求对应的server配置
  2. 设置当前server的读控制器(ssl、非ssl)
  3. 执行对应读控制器

2.1 SSL处理流程

  1. 创建ssl连接并完成握手
  2. 检查客户端证书
  3. 如果server配置中STARTTLS未关闭,执行对应协议的init_protocol
  4. 否则进入session初始化流程

2.2 非SSL处理流程

  • 直接进入session初始化流程

3. session初始化流程

协议 处理流程
IMAP 添加读事件、写事件
POP3 加盐处理、添加读事件、写事件
SMTP 添加读事件、写事件

4. 协议初始化流程

  1. 检查请求是否超时
  2. 创建临时缓冲区
  3. 读取客户端请求命令
  4. 解析命令并提取鉴权信息
  5. 发送至上游身份验证服务
  6. 根据返回结果处理
  7. 将结果发送给客户端

五、STREAM服务

1. 初始化流程

create_main_conf
create_srv_conf
preconfiguration
init_main_conf
merge_srv_conf
postconfiguration
ngx_stream_init_phase_handlers
ngx_stream_add_ports
ngx_stream_optimize_servers

优化监听列表

  • 相同端口有泛IP监听则忽略其他指定IP
  • 添加各server所需地址的监听
  • 设置监听参数(backlog、keepalive等)

2. 请求处理流程

阶段 类型 说明 处理函数
POST_ACCEPT_PHASE 读取请求内容 获取客户端真实IP ngx_stream_realip_handler
PREACCESS_PHASE 访问权限控制前 连接数限制 ngx_stream_limit_conn_handler
ACCESS_PHASE 访问权限控制 IP黑白名单 ngx_stream_access_handler
SSL_PHASE SSL连接 建立SSL连接 ngx_stream_ssl_handler
PREREAD_PHASE 请求数据预读 读取请求数据 ngx_stream_core_preread_phase
CONTENT_PHASE 内容生成 转发请求至上游 ngx_stream_core_content_phase
LOG_PHASE 日志记录 记录访问日志 ngx_stream_log_handler

六、参考文档

本文由佐柱撰写,转载请注明出处。欢迎访问我的小站