对比项目 | nginx | apache | 备注 |
进程结构 | master/worker | prefork thread mpm |
|
网络结构 | nio/aio | <=2.2 BIO >=2.4 BIO/NIO |
|
模块处理 | 异步callback | 大多同步处理 | |
内存管理 | 效率高,没有浪费 | 效率高,没有浪费 | |
反向代理 | upstream(三种工作模式) proxy(基于upstream) |
proxy/mod_jk |
├── core
├── event
├── http
├── misc
├── os
└── stream
/* 实现对各模块的整体控制,是 Nginx 程序 main 函数 */
├── nginx.c
├── nginx.h
/* 以下是基本数据结构及其操作 */
├── ngx_array.c
├── ngx_array.h
├── ngx_hash.c
├── ngx_hash.h
├── ngx_list.c
├── ngx_list.h
├── ngx_queue.c
├── ngx_queue.h
├── ngx_radix_tree.c
├── ngx_radix_tree.h
/* 红黑树实现 */
├── ngx_rbtree.c
├── ngx_rbtree.h
├── ngx_output_chain.c
├── ngx_buf.c
├── ngx_buf.h
/* 整个Nginx 模块构架基本配置管理 */
├── ngx_conf_file.c
├── ngx_conf_file.h
├── ngx_config.h
/* 网络连接管理 */
├── ngx_connection.c
├── ngx_connection.h
/* 定义一些头文件与结构别名 */
├── ngx_core.h
├── ngx_cpuinfo.c
/* CRC 校验表信息 */
├── ngx_crc32.c
├── ngx_crc32.h
├── ngx_crc.h
/* 实现对系统运行过程参数、资源的通用管理 */
├── ngx_cycle.c
├── ngx_cycle.h
/* 实现文件读写相关的功能 */
├── ngx_file.c
├── ngx_file.h
/* socket 网络套接字功能 */
├── ngx_inet.c
├── ngx_inet.h
/* 实现日志输出、管理的相关功能 */
├── ngx_log.c
├── ngx_log.h
├── ngx_syslog.c
├── ngx_syslog.h
/* hash字符串操作 */
├── ngx_md5.c
├── ngx_md5.h
├── ngx_murmurhash.c
├── ngx_murmurhash.h
/* 内存管理相关文件 */
├── ngx_open_file_cache.c
├── ngx_open_file_cache.h
├── ngx_palloc.c
├── ngx_palloc.h
├── ngx_shmtx.c
├── ngx_shmtx.h
├── ngx_slab.c
├── ngx_slab.h
/* PCRE 上层封装 */
├── ngx_parse.c
├── ngx_parse.h
/* 反向代理的协议信息 */
├── ngx_proxy_protocol.c
├── ngx_proxy_protocol.h
/* 实现支持正则表达式 */
├── ngx_regex.c
├── ngx_regex.h
/* 字符串处理功能 */
├── ngx_string.c
├── ngx_string.h
/* 时间获取与管理功能 */
├── ngx_times.c
└── ngx_times.h
/* 其他文件 */
├── ngx_resolver.c
├── ngx_resolver.h
├── ngx_sha1.h
├── ngx_spinlock.c
├── ngx_crypt.c
├── ngx_crypt.h
event 目录里面包含一种子目录 module 以及一些文件,除了 module 子目录,其他文件提供了事件驱动模型相关数据结构的定义、初始化、事件接收、传递、管理功能以及事件驱动模型调用功能。module 子目录里面的源码实现了Nginx 支持的事件驱动模型:AIO、epoll、kqueue、select、/dev/poll、poll 等事件驱动模型;
.
├── modules
│ ├── ngx_aio_module.c /* AIO 事件驱动模型 */
│ ├── ngx_devpoll_module.c /* dev/poll 事件驱动模型 */
│ ├── ngx_epoll_module.c /* epoll 事件驱动模型 */
│ ├── ngx_eventport_module.c /* 事件驱动模型端口 */
│ ├── ngx_kqueue_module.c /* kqueue 事件驱动模型 */
│ ├── ngx_poll_module.c /* poll 事件驱动模型 */
│ ├── ngx_rtsig_module.c /* rtsing 事件驱动模型 */
│ ├── ngx_select_module.c /* Linux 平台下的 select 事件驱动模型 */
│ └── ngx_win32_select_module.c /* Win32 平台下的 select 事件驱动模型 */
├── ngx_event_accept.c
├── ngx_event_busy_lock.c
├── ngx_event_busy_lock.h
├── ngx_event.c
├── ngx_event_connect.c
├── ngx_event_connect.h
├── ngx_event.h
├── ngx_event_mutex.c
├── ngx_event_openssl.c
├── ngx_event_openssl.h
├── ngx_event_openssl_stapling.c
├── ngx_event_pipe.c
├── ngx_event_pipe.h
├── ngx_event_posted.c
├── ngx_event_posted.h
├── ngx_event_timer.c
└── ngx_event_timer.h
Nginx 基础数据结构
整型数据
/* Nginx 简单数据类型 */
/* 在文件 src/core/ngx_config.h 定义了基本的数据映射 */
typedef intptr_t ngx_int_t;
typedef uintptr_t ngx_uint_t;
typedef intptr_t ngx_flag_t;
typedef unsigned long int uintptr_t;
typedef int intptr_t;
typedef unsigned int uintptr_t;
/* 因此,Nginx 的简单数据类型的操作和整型或指针类型类似 */
字符串类型
/* Nginx 字符串数据类型 */
/* Nginx 字符串类型是对 C 语言字符串类型的简单封装,
* 其定义在 core/ngx_string.h 或 core/ngx_string.c 中
* 定义了 ngx_str_t, ngx_keyval_t, ngx_variable_value_t
*/
/* ngx_str_t 在 u_char 的基础上增加了字符串长度的信息,即len变量 */
typedef struct {
size_t len; /* 字符串的长度 */
u_char *data; /* 指向字符串的第一个字符 */
} ngx_str_t;
内存池类型
/* 内存池结构 */
typedef struct {/* 内存池数据结构模块 */
u_char *last; /* 当前内存分配的结束位置,即下一段可分配内存的起始位置 */
u_char *end; /* 内存池的结束位置 */
ngx_pool_t *next; /* 指向下一个内存池 */
ngx_uint_t failed;/* 记录内存池内存分配失败的次数 */
} ngx_pool_data_t; /* 维护内存池的数据块 */
struct ngx_pool_s {/* 内存池的管理模块,即内存池头部结构 */
ngx_pool_data_t d; /* 内存池的数据块 */
size_t max; /* 内存池数据块的最大值 */
ngx_pool_t *current;/* 指向当前内存池 */
ngx_chain_t *chain;/* 指向一个 ngx_chain_t 结构 */
ngx_pool_large_t *large;/* 大块内存链表,即分配空间超过 max 的内存 */
ngx_pool_cleanup_t *cleanup;/* 析构函数,释放内存池 */
ngx_log_t *log;/* 内存分配相关的日志信息 */
};
/* 文件 core/ngx_core.h */
typedef struct ngx_pool_s ngx_pool_t;
缓冲区数据类型
缓冲区 ngx_buf_t 的定义如下:
/* 缓冲区结构 */
typedef struct ngx_buf_s ngx_buf_t;
struct ngx_buf_s {
u_char *pos; /* 缓冲区数据在内存的起始位置 */
u_char *last; /* 缓冲区数据在内存的结束位置 */
/* 这两个参数是处理文件时使用,类似于缓冲区的pos, last */
off_t file_pos;
off_t file_last;
/* 由于实际数据可能被包含在多个缓冲区中,则缓冲区的start和end指向
* 这块内存的开始地址和结束地址,
* 而pos和last是指向本缓冲区实际包含的数据的开始和结尾
*/
u_char *start; /* start of buffer */
u_char *end; /* end of buffer */
~~blabla~~
};
chain 数据类型
ngx_chain_t 数据类型是与缓冲区类型 ngx_buf_t 相关的链表结构,定义如下:
struct ngx_chain_s {
ngx_buf_t *buf; /* 指向当前缓冲区 */
ngx_chain_t *next; /* 指向下一个chain,形成chain链表 */
};
typedef struct ngx_chain_s ngx_chain_t;
链表图如下:
extern volatile ngx_cycle_t *ngx_cycle;
nginx conf
core/upstream/
main/srv/loc config
#define NGX_DIRECT_CONF 0x00010000
#define NGX_MAIN_CONF 0x01000000
#define NGX_ANY_CONF 0x0F000000
#define NGX_EVENT_CONF 0x02000000
#define NGX_HTTP_MAIN_CONF 0x02000000
#define NGX_HTTP_SRV_CONF 0x04000000
#define NGX_HTTP_LOC_CONF 0x08000000
#define NGX_HTTP_UPS_CONF 0x10000000
#define NGX_HTTP_SIF_CONF 0x20000000
#define NGX_HTTP_LIF_CONF 0x40000000
#define NGX_HTTP_LMT_CONF 0x80000000
nginx 的时间是缓存的时间,如果需要获得最新时间,需要调用ngx_time_update来更新时间,
详细:http://blog.csdn.net/mrzhangjwei/article/details/77150335
在 Nginx 中定时器事件的实现与内核无关,是通过红黑树来实现。在事件模块中,当等待的事件不能在指定的时间内到达,则会触发Nginx 的超时机制,超时机制会对发生超时的事件进行管理,并对这些超时事件作出处理。对于定时事件的管理包括两方面:定时事件对象的组织形式 和 定时事件对象的超时检测。
EveryThing Is event driven.
epoll/kqueue/select/poll/aio :
https://www.cnblogs.com/linganxiong/p/5583415.html
https://www.nginx.com/blog/thread-pools-boost-performance-9x/
NGX_AGAIN/NGX_ERROR/NGX_OK
多次调用同一个处理函数,需要从同步编程模式转换到异步编程思维,中间变量都是通过context来保存。
client/upstream/other module 只要是可以抽象为文件的,都需要占用一个
file descriptor
三种工作模式
根据buffer_size的大小,工作方式不一致,如果buffer太小,会导致写盘操作,所以需要配置的时候进来可以覆盖大部分upstream返回值大小。
除了上述几个核心模块之外,其他一切皆为模块。
typedef enum {
NGX_HTTP_POST_READ_PHASE = 0,
NGX_HTTP_SERVER_REWRITE_PHASE,
NGX_HTTP_FIND_CONFIG_PHASE,
NGX_HTTP_REWRITE_PHASE,
NGX_HTTP_POST_REWRITE_PHASE,
NGX_HTTP_PREACCESS_PHASE,
NGX_HTTP_ACCESS_PHASE,
NGX_HTTP_POST_ACCESS_PHASE,
NGX_HTTP_TRY_FILES_PHASE,
NGX_HTTP_CONTENT_PHASE,
NGX_HTTP_LOG_PHASE
} ngx_http_phases;
https://www.kancloud.cn/digest/understandingnginx/202595