Nginx 框架使用手册
1. 概述
Nginx是一个高性能的HTTP和反向代理服务器,同时也是一个IMAP/POP3/SMTP服务器。本手册将深入分析Nginx的源码架构,帮助开发者理解其内部工作机制。
2. 项目结构
nginx/
├── auto/ # 自动构建脚本
├── conf/ # 配置文件模板
├── contrib/ # 贡献的工具和脚本
├── docs/ # 文档
├── misc/ # 杂项文件
└── src/ # 源代码
├── core/ # 核心模块
├── event/ # 事件模块
├── http/ # HTTP模块
├── mail/ # 邮件代理模块
├── misc/ # 杂项模块
├── os/ # 操作系统相关
└── stream/ # 流代理模块
3. 核心概念
3.1 模块化架构
Nginx采用高度模块化的设计,每个功能都被封装在独立的模块中:
- 核心模块(Core Module): 提供基础功能
- 事件模块(Event Module): 处理网络事件
- HTTP模块(HTTP Module): 处理HTTP协议
- Mail模块(Mail Module): 处理邮件代理
- Stream模块(Stream Module): 处理TCP/UDP代理
3.2 进程模型
Nginx使用多进程模型:
- Master进程: 管理Worker进程,处理信号
- Worker进程: 处理客户端请求
- Cache Manager进程: 管理缓存
- Cache Loader进程: 加载缓存
3.3 事件驱动
Nginx使用事件驱动的异步非阻塞模型:
- 支持epoll、kqueue、select等多种事件机制
- 单个Worker进程可以处理数千个并发连接
- 内存占用低,性能高
4. 主要数据结构
4.1 ngx_cycle_t - 核心周期结构
struct ngx_cycle_s {
void ****conf_ctx; // 配置上下文
ngx_pool_t *pool; // 内存池
ngx_log_t *log; // 日志
ngx_connection_t **files; // 文件连接
ngx_connection_t *free_connections; // 空闲连接
ngx_module_t **modules; // 模块数组
ngx_array_t listening; // 监听端口
ngx_list_t open_files; // 打开的文件
ngx_cycle_t *old_cycle; // 旧的周期
};
4.2 ngx_module_t - 模块结构
struct ngx_module_s {
ngx_uint_t ctx_index; // 上下文索引
ngx_uint_t index; // 模块索引
char *name; // 模块名称
ngx_uint_t spare0;
ngx_uint_t spare1;
ngx_uint_t version; // 版本
const char *signature; // 签名
void *ctx; // 模块上下文
ngx_command_t *commands; // 命令数组
ngx_uint_t type; // 模块类型
// 生命周期回调函数
ngx_int_t (*init_master)(ngx_log_t *log);
ngx_int_t (*init_module)(ngx_cycle_t *cycle);
ngx_int_t (*init_process)(ngx_cycle_t *cycle);
ngx_int_t (*init_thread)(ngx_cycle_t *cycle);
void (*exit_thread)(ngx_cycle_t *cycle);
void (*exit_process)(ngx_cycle_t *cycle);
void (*exit_master)(ngx_cycle_t *cycle);
};
4.3 ngx_connection_t - 连接结构
struct ngx_connection_s {
void *data; // 连接数据
ngx_event_t *read; // 读事件
ngx_event_t *write; // 写事件
ngx_socket_t fd; // 文件描述符
ngx_recv_pt recv; // 接收函数指针
ngx_send_pt send; // 发送函数指针
ngx_recv_chain_pt recv_chain; // 接收链函数指针
ngx_send_chain_pt send_chain; // 发送链函数指针
ngx_listening_t *listening; // 监听结构
off_t sent; // 已发送字节数
ngx_log_t *log; // 日志
ngx_pool_t *pool; // 内存池
int type; // 连接类型
struct sockaddr *sockaddr; // 套接字地址
socklen_t socklen; // 地址长度
ngx_str_t addr_text; // 地址文本
};
5. 启动流程
5.1 主函数入口
int main(int argc, char *const *argv)
{
// 1. 初始化调试信息
ngx_debug_init();
// 2. 初始化错误字符串
if (ngx_strerror_init() != NGX_OK) {
return 1;
}
// 3. 解析命令行参数
if (ngx_get_options(argc, argv) != NGX_OK) {
return 1;
}
// 4. 初始化时间
ngx_time_init();
// 5. 初始化日志
log = ngx_log_init(ngx_prefix, ngx_error_log);
// 6. 初始化操作系统相关
if (ngx_os_init(log) != NGX_OK) {
return 1;
}
// 7. 预初始化模块
if (ngx_preinit_modules() != NGX_OK) {
return 1;
}
// 8. 初始化周期
cycle = ngx_init_cycle(&init_cycle);
// 9. 根据配置选择进程模式
if (ngx_process == NGX_PROCESS_SINGLE) {
ngx_single_process_cycle(cycle);
} else {
ngx_master_process_cycle(cycle);
}
return 0;
}
5.2 初始化周期详解
ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle)
{
// 1. 创建内存池
pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);
// 2. 分配周期结构
cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t));
// 3. 初始化基本信息
cycle->pool = pool;
cycle->log = log;
cycle->old_cycle = old_cycle;
// 4. 解析配置文件
conf.ctx = cycle->conf_ctx;
conf.cycle = cycle;
conf.pool = pool;
conf.log = log;
conf.module_type = NGX_CORE_MODULE;
conf.cmd_type = NGX_MAIN_CONF;
if (ngx_conf_param(&conf) != NGX_CONF_OK) {
environ = senv;
ngx_destroy_cycle_pools(&conf);
return NULL;
}
if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
environ = senv;
ngx_destroy_cycle_pools(&conf);
return NULL;
}
// 5. 初始化模块
if (ngx_init_modules(cycle) != NGX_OK) {
exit(1);
}
return cycle;
}
6. 配置系统
6.1 配置指令结构
struct ngx_command_s {
ngx_str_t name; // 指令名称
ngx_uint_t type; // 指令类型
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
ngx_uint_t conf; // 配置偏移
ngx_uint_t offset; // 结构偏移
void *post; // 后处理函数
};
6.2 配置解析流程
- 词法分析: 将配置文件分解为token
- 语法分析: 根据指令定义解析配置
- 语义分析: 验证配置的合法性
- 配置应用: 将配置应用到相应的模块
7. 内存管理
7.1 内存池设计
Nginx使用内存池来管理内存,避免频繁的malloc/free操作:
struct ngx_pool_s {
ngx_pool_data_t d; // 池数据
size_t max; // 最大分配大小
ngx_pool_t *current; // 当前池
ngx_chain_t *chain; // 缓冲区链
ngx_pool_large_t *large; // 大块内存
ngx_pool_cleanup_t *cleanup; // 清理函数
ngx_log_t *log; // 日志
};
7.2 内存分配策略
- 小块内存: 直接从内存池分配
- 大块内存: 单独分配,加入large链表
- 对齐分配: 保证内存对齐,提高访问效率
8. 日志系统
8.1 日志级别
#define NGX_LOG_STDERR 0
#define NGX_LOG_EMERG 1
#define NGX_LOG_ALERT 2
#define NGX_LOG_CRIT 3
#define NGX_LOG_ERR 4
#define NGX_LOG_WARN 5
#define NGX_LOG_NOTICE 6
#define NGX_LOG_INFO 7
#define NGX_LOG_DEBUG 8
8.2 日志结构
struct ngx_log_s {
ngx_uint_t log_level; // 日志级别
ngx_open_file_t *file; // 日志文件
ngx_atomic_uint_t connection; // 连接号
time_t disk_full_time; // 磁盘满时间
ngx_log_handler_pt handler; // 处理函数
void *data; // 数据
ngx_log_writer_pt writer; // 写入函数
void *wdata; // 写入数据
char *action; // 当前动作
ngx_log_t *next; // 下一个日志
};
9. 使用示例
9.1 编写自定义模块
// 模块上下文
typedef struct {
ngx_str_t name;
} ngx_hello_conf_t;
// 配置指令
static ngx_command_t ngx_hello_commands[] = {
{
ngx_string("hello"),
NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_hello_set,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_hello_conf_t, name),
NULL
},
ngx_null_command
};
// 模块定义
ngx_module_t ngx_hello_module = {
NGX_MODULE_V1,
&ngx_hello_module_ctx,
ngx_hello_commands,
NGX_HTTP_MODULE,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NGX_MODULE_V1_PADDING
};
9.2 处理HTTP请求
static ngx_int_t
ngx_hello_handler(ngx_http_request_t *r)
{
ngx_buf_t *b;
ngx_chain_t out;
// 设置响应头
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.content_length_n = sizeof("Hello World!") - 1;
// 创建响应体
b = ngx_create_temp_buf(r->pool, sizeof("Hello World!") - 1);
b->pos = (u_char *) "Hello World!";
b->last = b->pos + sizeof("Hello World!") - 1;
b->last_buf = 1;
out.buf = b;
out.next = NULL;
// 发送响应
return ngx_http_output_filter(r, &out);
}
10. 性能优化要点
10.1 内存优化
- 使用内存池减少内存碎片
- 预分配常用数据结构
- 避免频繁的内存分配和释放
10.2 网络优化
- 使用事件驱动模型
- 支持多种事件机制(epoll, kqueue等)
- 连接复用和长连接
10.3 CPU优化
- Worker进程绑定CPU核心
- 减少系统调用次数
- 优化数据结构访问模式
11. 调试技巧
11.1 编译调试版本
./configure --with-debug
make
11.2 使用GDB调试
gdb nginx
(gdb) set args -c /path/to/nginx.conf
(gdb) run
11.3 日志调试
error_log /var/log/nginx/debug.log debug;
12. 总结
Nginx的设计体现了以下几个重要思想:
- 模块化: 功能高度模块化,易于扩展
- 事件驱动: 异步非阻塞,高并发处理
- 内存池: 高效的内存管理
- 多进程: 稳定可靠的进程模型
- 配置驱动: 灵活的配置系统
通过深入理解这些设计思想和实现细节,开发者可以更好地使用和扩展Nginx。