- Nginx 把所有 socket(包括 listen socket)都统一抽象成 ngx_connection_t。
- Nginx 把所有 epoll/kqueue 事件都统一抽象成 ngx_event_t。
- Nginx 把所有协议都统一抽象成 ngx_protocol_t。
- Nginx 把所有模块都统一抽象成 ngx_module_t。
第一章:Nginx 网络模型与协议架构核心设计
Nginx 的核心并不是 HTTP 服务器,而是一个基于事件驱动的通用网络框架。HTTP、TCP、UDP 等协议都只是构建在其网络抽象之上的“插件”。
理解 nginx 源码的关键,不在于协议细节,而在于它的 网络层三大基础对象模型。
一、Nginx 网络模型的本质
nginx 的设计非常克制,它没有像传统服务器那样为每种协议构建独立网络栈,而是统一抽象为:
事件驱动 + 连接驱动 + 状态机驱动
所有网络行为都围绕 epoll/kqueue 事件展开:
- 连接建立
- 数据读写
- 超时处理
- 关闭连接
这些全部由事件系统驱动。
二、Nginx 的三大网络基础对象(核心章节)
这是理解 nginx 源码的“第一性原理”。
2.1 三个核心对象
nginx 的网络层实际上只有三个基础对象:
| 对象 | 作用 | 所在层 |
|---|---|---|
ngx_listening_t | 监听 socket(listen 端口) | core |
ngx_connection_t | TCP 连接抽象 | core |
ngx_event_t | epoll/kqueue 事件 | event |
2.2 三者关系模型
1
2
3
4
5
6
7
8
9
10
Nginx 网络核心
│
┌───────────┼───────────┐
│ │ │
ngx_listening_t ngx_event_t ngx_connection_t
(监听socket) (事件) (TCP连接)
│ │
└───────────┬───────────────┘
▼
连接生命周期
2.3 三个对象的职责
(1)ngx_listening_t —— 监听 socket
它表示一个 listen 端口,例如:
1
2
3
listen 80;
listen 443;
listen 3306;
本质是对系统 listen socket 的封装。
关键字段:
- fd:监听 socket
- sockaddr:地址信息
- handler:accept 后的入口函数
- backlog / buffer 配置
👉 最关键字段:
handler(协议分发入口)
它决定 accept 后进入哪个模块:
- HTTP → ngx_http_init_connection
- STREAM → ngx_stream_init_connection
- MAIL → ngx_mail_init_connection
(2)ngx_connection_t —— TCP连接抽象
这是 nginx 最核心的数据结构。
所有连接都是它:
- client → nginx
- nginx → upstream
- listen socket 本身
关键字段:
- fd:连接描述符
- read/write event
- data:协议对象挂载点
👉 关键设计点:
ngx_connection_t 不绑定协议
协议是后面挂的。
(3)ngx_event_t —— IO事件
表示 epoll/kqueue 的事件:
- EPOLLIN(可读)
- EPOLLOUT(可写)
- error
- timeout
核心字段:
- handler:事件回调函数
- active:是否注册
nginx 的 IO 本质是:
event → handler → 状态机推进
2.4 一个核心总结
nginx 网络层只有三个对象:
ngx_listening_t + ngx_connection_t + ngx_event_t
所有 HTTP / TCP / UDP 逻辑都建立在这三者之上。
三、协议层对象(HTTP / stream / mail)
在网络层之上,nginx 才引入协议层。
协议层的本质:
挂在 ngx_connection_t 上的状态机
3.1 协议对象列表
| 模块 | 协议对象 |
|---|---|
| http | ngx_http_request_t |
| stream | ngx_stream_session_t |
| ngx_mail_session_t |
3.2 协议对象挂载方式
核心机制:
1
2
3
4
ngx_connection_t
│
▼
void *data
不同协议挂不同对象:
HTTP
1
c->data = ngx_http_request_t
STREAM
1
c->data = ngx_stream_session_t
1
c->data = ngx_mail_session_t
3.3 本质理解
ngx_connection_t = 通用 TCP 连接 协议对象 = 连接上的状态机
四、完整连接生命周期
一个 TCP 请求在 nginx 中的完整路径:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
客户端连接
│
▼
ngx_listening_t(监听socket)
│
▼
epoll 触发
│
▼
ngx_event_accept()
│
▼
accept() 获取 fd
│
▼
ngx_connection_t 创建
│
▼
ls->handler(c)
│
├── HTTP → ngx_http_init_connection
│ └── ngx_http_request_t
│
├── STREAM → ngx_stream_init_connection
│ └── ngx_stream_session_t
│
└── MAIL → ngx_mail_init_connection
└── ngx_mail_session_t
五、为什么 Nginx 可以支持多协议
因为它做了三层解耦:
5.1 网络层统一
所有 IO 统一:
- ngx_connection_t
- ngx_event_t
5.2 协议层插件化
协议模块只需要实现:
- 初始化连接
- 状态机处理
- 事件回调
5.3 协议与网络完全分离
core 不关心:
- HTTP
- TCP proxy
- TLS
core 只负责:
epoll + connection + event
六、stream 模块的本质
以 stream 为例:
1
2
3
4
5
6
7
8
9
10
11
12
13
client TCP
│
▼
ngx_connection_t
│
▼
ngx_stream_session_t
│
▼
proxy_pass
│
▼
upstream connection
stream 的特点:
- 不解析 HTTP
- 不关心应用层协议
- 只处理字节流
七、Nginx 架构的本质总结
nginx 实际是一个:
事件驱动的通用网络框架,而不是 HTTP Server
它的核心模型:
1
event → connection → protocol state machine
八、本章核心总结
请记住这一张图:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Nginx 网络模型
────────────────────────────
ngx_listening_t → 监听socket
│
▼
ngx_event_t → epoll事件
│
▼
ngx_connection_t → TCP连接
│
▼
protocol object → HTTP / STREAM / MAIL
│
▼
state machine → 请求/会话处理
第二章:ngx_event_accept 函数

核心就一句话:lc 是门,c 是进来的客人。
lc 是 nginx 启动时就创建好的”监听连接”,它的 fd 是 bind()+listen() 之后的监听 socket。这个 socket 不能读数据,只能调 accept()。epoll 检测到它”可读”的意思不是”有数据来了”,而是”有新的 TCP 连接在排队等着被接受”。整个 worker 进程跑起来,lc 就一直在那,永远不会关闭。
c 是每次 accept4(lc->fd, ...) 后产生的,内核从等待队列里取出一个已完成三次握手的连接,返回一个全新的 fd。nginx 再从预分配的连接池里取一个 ngx_connection_t 对象绑上这个新 fd,这才是 c。后续所有读写数据、HTTP 解析、WAF 检测,都在 c 上进行。请求结束后 c 放回池子,但 lc 全程没动过。
所以 lc = ev->data 这行的意思是:epoll 触发了,ev 就是 lc 的读事件,ev->data 指回 lc 本身,再从 lc->listening 拿到配置 ls。这三行就是”确认是哪个端口的事件触发了,拿到对应的配置”。之后 accept4() 一调,lc 的使命在这次循环里就结束了,接下来全是 c 的事。