参考:
作者将此书分为三大块,前一二两章为第一部分,着重于如何使用 Nginx。第二部分的范围为三至七章,通过 e.g. 介绍 HTTP模块 的开发方式。第八章之后为第三部分,介绍 Nginx 的完整框架。
此书于 2016 年出版,出版时支持到 Nginx 版本 1.8.0。如与最新版本使用有差异,我会尽可能在笔记中标注。
Nginx 简介
具备 Web 服务器相应的功能:基于 REST 架构风格,以 URI 或 URL 作为沟通依据,通过 HTTP 为客户端程序提供网络服务。
Apache 目前占有量最高,拥有稳定、开源、跨平台等优异特性,但由于其重量级的设计,在高并发环境下,会导致服务器CPU资源和内存的大量占用。
Nginx 由俄罗斯的 Igor Sysoev 使用 C语言 开发,开源许可证为 2-clause BSD-like license。Nginx 的优点如下:
- 快速响应
- 高扩展性
- 高可靠性
- 低内存消耗
- 高并发支持
- 热部署
Nginx 采用事件驱动设计、全异步网络I/O处理机制、低进程间切换设计等,尽可能的减少资源消耗。
环境配置
我以 CentOS 8.2 作为服务器环境,Nginx 的编译需要以下几个较为基础的组件:
- gcc
- gcc-c++
- pcre, pcre-devel
- zlib, zlib-devel
- openssl, openssl-devel
关于 Linux 内核参数优化
修改 /etc/sysctl.conf 来更改内核参数:
# 进程可以同时打开的最大句柄数,直接限制最大并发连接数
fs.file-max = 999999
# 1 表示允许将TIME-WAIT状态的socket重新用于新的TCP连接
# 这对于服务器来说很有意义,因为服务器上总会有大量TIME-WAIT状态的连接
net.ipv4.tcp_tw_reuse = 1
# 表示当keepalive启用时,TCP发送keepalive消息的频率,设置值小可以更快清理无效连接
net.ipv4.tcp_keepalive_time = 600
# 这个参数表示当服务器主动关闭连接时,socket保持在FIN-WAIT-2状态的最大时间
net.ipv4.tcp_fin_timeout = 30
# 这个参数表示操作系统允许TIME_WAIT套接字数量的最大值
# 如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息,套接字过多会使Web服务器变慢
net.ipv4.tcp_max_tw_buckets = 5000
# 定义了在UDP和TCP连接中本地(不包括连接的远端)端口的取值范围
net.ipv4.ip_local_port_range = 1024 61000
# 定义了TCP接收缓存(用于TCP接收滑动窗口)的最小值、默认值、最大值
net.ipv4.tcp_rmem = 4096 32768 262142
# 定义了TCP发送缓存(用于TCP发送滑动窗口)的最小值、默认值、最大值
net.ipv4.tcp_wmem = 4096 32768 262142
# 当网卡接收数据包的速度大于内核处理的速度时,会有一个队列保存这些数据包
# 表示队列最大值
net.core.netdev_max_backlog = 8096
# 表示内核套接字接收缓存区默认的大小
net.core.rmem_default = 262144
# 表示内核套接字发送缓存区默认的大小
net.core.wmem_default = 262144
# 表示内核套接字接收缓存区的最大大小
net.core.rmem_max = 2097152
# 表示内核套接字发送缓存区的最大大小
net.core.wmem_max = 2097152
# 用于解决TCP的SYN攻击
net.ipv4.tcp_syncookies = 1
# 表示TCP三次握手建立阶段接收SYN请求队列的最大长度,默认为1024
# 大一些可以使出现Nginx来不及accept新连接的情况时,Linux不至于丢失客户端发起的连接请求
net.ipv4.tcp_max_syn.backlog=1024
执行 sysctl-p 生效修改。
编译和安装
创建文件夹,使用 wget 下载 nginx 并解压,这里下载 2023-01-29 时的稳定版本:
wget http://nginx.org/download/nginx-1.22.1.tar.gz
tar -zxvf nginx-1.22.1.tar.gz
// 进入解压后的文件夹 nginx-1.22.1
cd nginx-1.22.1
// 检测系统内核和已安装软件,解析参数,生成 C源码文件 和 Makefile 文件
// configure 附加参数可自行查找
./configure
// 根据 configure 命令生成的 Makefile 文件编译 Nginx 工程
make
// 根据 configure 执行时的参数将 Nginx 部署到指定安装目录
make install
需要在 configure 执行时对编译做自定义修改,可以参考 Configure Command Parameters
书中对 configure 的具体执行做了详细的介绍,但是私以为 C基础较弱的读者或初学者,在 Nginx 的学习早期了解这些帮助并不大,遂先跳过。
安装完成后,可以通过 nginx -V 查看配置编译阶段的信息,如GCC编译器的版本、操作系统的版本、执行configure时的参数等。
控制命令
// 默认启动
nginx
// 指定配置文件
nginx -c [nginx_conf_file]
// 指定安装目录(设置前缀路径)
nginx -p /usr/local/nginx/
// 指定全局配置项 e.g.
// 通过 -g "" 启动的 nginx 执行其他命令时,也需要带上 -g ""
nginx -g "pid /var/nginx/test.pid"
// 测试配置信息是否有误
nginx -t
// 在测试配置阶段不输出信息(-q 可以屏蔽 error 级别以下的信息)
nginx -t -q
// 显示版本信息
nginx -v
// 显示编译阶段的参数
nginx -V
// 快速停止服务,与 kill 等效
nginx -s stop
// 优雅停止服务
nginx -s quit
// 刷新配置
nginx -s reload
// 日志文件回滚
nginx -s reopen
Nginx 配置
Nginx 进程关系
Nginx 进程分为 master 进程和 worker 进程。相似于 kubernetes 中的 master 和 worker,master 进程只负责监控管理 worker 进程,worker 进程数量通常和 CPU 核心数量相等。
Worker 进程之间通过共享内存、原子操作(负载均衡锁)等进程间通信机制来实现负载均衡等功能。
这样设计的好处在:
- 由于 master 进程不会对用户请求提供服务,只用于管理真正提供服务的 worker 进程,所以 master 进程可以是唯一的,它仅专注于自己的纯管理工作
- master 进程需要拥有较大的权限,worker 进程的权限要小于或等于 master 进程,这样 master 进程才可以完全地管理worker进程,当任意一个 worker 进程出现错误从而导致 coredump 时,master 进程会立刻启动新的 worker 进程继续服务
- 多个 worker 进程处理互联网请求可以提高服务的健壮性,也可以充分利用现在常见的 SMP 多核架构,从而实现微观上真正的多核并发处理
为什么要把 worker 进程数量设置得与 CPU核心数量 一致?
在 Apache 上每个进程在一个时刻只处理一个请求,因此,如果希望 Web服务器 拥有并发处理的请求数更多,就要把 Apache 的进程或线程数设置得更多,通常会达到一台服务器拥有几百个工作进程,这样大量的进程间切换将带来无谓的系统资源消耗。但使用进程的优势在于连接稳定,进程死掉后不会影响其他进程。
Nginx在处理用户请求时采用的是线程,而线程是共享内存的,多个线程共享 worker 进程的内存,一个 worker 进程可以同时处理的请求数只受限于内存大小。在架构设计上,不同的 worker 进程之间处理并发请求时几乎没有同步锁的限制,worker 进程通常不会进入睡眠状态,因此,当 Nginx 上的进程数与 CPU核心数 相等时(最好每一个 worker 进程都绑定特定的 CPU核心),进程间切换的代价是最小的。这种模式的缺点是,稳定性差,当一个进程死掉时,会影响到多个用户的使用。
Nginx 配置通用语法
块配置项
e.g.
events {
}
http {
upstream backend {
server 127.0.0.1:8080;
}
gzip on;
server {
location /webstatic {
gzip off;
}
}
}
上述示例 events、http、server、location、upstream 都是块配置项。块配置项一定会用大括号把一系列所属的配置项全包含进来,表示大括号内的配置项同时生效。所有的事件类配置都要在 events 块中,http、server 等配置也遵循这个规定。
块配置项可以嵌套。内层块直接继承外层块。当内外层块中的配置发生冲突时,究竟是以内层块还是外层块的配置为准,取决于解析这个配置项的模块。如上述示例中,最终 /webstatic 的处理模块中,gzip 模块是按照 off 来处理请求的。
配置项
格式为:
[配置项名] [配置项值1] [配置项值2等];
# 如上述示例中
server 127.0.0.1:8080;
# 关于配置项的单位
# 空间
K - (千字节)
M - (兆字节)
# 时间
ms - (毫秒)
s - (秒)
m - (分)
h - (时)
d - (日)
w - (周)
M - (月)
y - (年)
变量
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';
变量通过 ‘$’ 符号标识(并非所有模块都支持处理变量)。
在执行 configure 命令时,我们已经把许多模块编译进 Nginx 中,但是否启用这些模块,一般取决于配置文件中相应的配置项。 换句话说,每个 Nginx 模块都有自己感兴趣的配置项,大部分模块都必须在 nginx.conf 中读取某个配置项后才会在运行时启用。 例如,只有当配置http{...}这个配置项时,ngx_http_module 模块才会在 Nginx 中启用,其他依赖 ngx_http_module 的模块也才能正常使用。
基本配置
Nginx 在运行时,至少需要加载几个核心模块和一个事件类模块。支持这些模块运行的配置项称为基本配置——所有其他模块执行时都依赖的配置项。
大致分为四类:
- 用于调试、定位问题的配置项
- 正常运行的必备配置项
- 优化性能的配置项
- 事件类配置项
还有一些默认配置项(e.g. daemon),即使 nginx.conf 中没有对它进行显式配置,也会默认开启。对于这样的配置项,作者会在下面相应的配置项描述上加入一行“默认:”来进行说明。
用于调试、定位问题的配置项
# 1. 是否以守护进程方式运行 Nginx
daemon on|off;
# default
# 手动关闭 daemon 用于方便跟踪调试 nginx
daemon on;
---
# 2. 是否以 master/worker 方式工作
master_process on|off;
# default
# 手动关闭 master_process 用于方便跟踪调试 nginx
master_process on;
---
# 3. Error 日志设置
error_log [/path/file] [level];
# default [/path/file] 为具体文件,level 可以是 debug|info|notice|warn|error|crit|alert|emerg 级别依次递增
# 大于等于该级别的日志都会输入到 [file] 中
error_log logs/error.log error;
---
# 4. 仅对指定的客户端输出debug级别的日志
debug_connection [IP|CIDR]
# 表示来自以下 IP地址 的请求才会输出 debug 级别的日志,其他依然沿用 error_log 的配置
# 使用此命令前确保 configure 时已经加入了 --with-debug 参数
# e.g.
events {
debug_connection 10.224.66.14;
debug_connection 10.224.57.0/24;
}
---
# 5. 限制 coredump 核心转储文件的大小
# 避免意外终止时产生的 coredump 文件占用过多磁盘
worker_rlimit_core size;
---
# 6. 指定 coredump 文件生成目录
working_directory path;
正常运行的配置项
# 1. 定义环境变量
env VAR|VAR=VALUE;
# e.g.
env TESTPATH=/tmp/;
---
# 2. 嵌入其他配置文件
include /path/file;
# e.g.
include time.types;
include vhost/*.conf;
---
# 3. 保存 master 进程ID 的 pid 文件存放路径
pid /path/file;
# e.g.
pid logs/nginx.pid;
---
# 4. Nginx worker 进程运行的用户及用户组
user username[groupname];
# e.g.
# user 用于设置 master 进程启动后,fork 出的 worker 进程运行在哪个用户和用户组下
# 若用户在 configure 命令执行时使用了参数 --user=username 和 --group=groupname ,此时 nginx.conf 将使用参数中指定的用户和用户组
user nobody nobody;
---
# 5. 指定 Nginx worker 进程可以打开的最大句柄描述符个数
worker_rlimit_nofile limit;
---
# 6. 限制信号队列
# 设置每个用户发往 Nginx 的信号队列的大小。当某个用户的信号队列满了,这个用户再发送的信号量会被丢掉。
worker_rlimit_sigpending limit;
优化性能的配置项
# 1. Nginx worker 进程个数
# worker 进程是单线程的进程,会调用各个模块完成对应任务
# 模块不会出现阻塞式调用 -> 与 CPU 内核数对应
# 模块有可能出现阻塞式调用 -> 增加 worker 进程数
# 多 worker 进程会导致进程间切换开销,关键在于控制 阻塞开销 和 进程切换开销
worker_processes number;
# e.g.
worker_processes 1;
# 2. 绑定 Nginx worker 进程到指定的 CPU内核
# worker 进程独享 CPU 有助于在内核调度策略上实现完全并发
# Linux 会调用 sched_setaffinity()
worker_cpu_affinity cpumask [cpumask ...];
# e.g.
worker_processes 4;
worker_cpu_affinity 1000 0100 0010 0001;
# 3. SSL 硬件加速
# 若服务器上有 SSL 硬件加速设备,那么就可以进行配置以加快 SSL 协议的处理速度
ssl_engine device;
# 用户可以使用 OpenSSL 提供的命令来查看是否有 SSL 硬件加速设备
openssl engine -t
# 4. 系统调用 gettimeofday 的执行频率(x86-64 架构开销小 无需设置)
# 默认每次内核的事件调用后都会执行 gettimeofday,实现用内核的时钟来更新 Nginx 中的缓存时钟
timer_resolution t;
e.g.
# 至少每 100ms 才调用一次 gettimeofday
timer_resolution 100ms;
# 5. Nginx worker 进程优先级设置,nice 范围为 -20 到 +19,值越低优先级越高
worker_priority nice;
# e.g.
# default
worker_priority 0;
事件类配置项
# 1. 是否打开 accept 锁
# Nginx 的负载均衡锁,可以让多个 worker 进程轮流地、序列化地与新的客户端建立 TCP 连接
# 实现所有 worker 进程之上处理的客户端请求数接近
accept_mutex on|off;
# e.g.
# default
accept_mutex on;
# 2. lock 文件的路径(不常用)
# 由于编译程序、操作系统架构等因素导致 Nginx 不支持原子锁,则使用 lock 文件实现 accept 锁
lock_file /path/file
# e.g.
# default
lock_file logs/nginx.lock
# 3. 使用 accpt 锁后到真正建立连接之间的延迟时间
# 使用 accept 锁后,同一时间只有一个 worker 进程能够获取到 accept 锁
# 此 accept 锁不是阻塞锁,如果取不到会立刻返回
# 某 worker 进程尝试获取 accept 锁而未取得,要等待 accept_mutex_delay 的时间才能再次尝试
accept_mutex_delay Nms;
# e.g.
# default
accept_mutex_delay 500ms;
# 4. 批量建立新连接
# 当事件模型通知有新连接时,尽可能地对本次调度中客户端发起的所有 TCP 请求都建立连接
multi_accept on|off;
# e.g.
# default
multi_accept off;
# 5. 选择事件模型
use [kqueue|rtsig|epoll|/dev/poll|select|poll|eventport];
# default Nginx 自动选择
# 对于 Linux 操作系统来说,可供选择的事件驱动模型有poll、select、epoll三种
# 6. 每个worker的最大连接数
# 定义每个 worker 进程可以同时处理的最大连接数
worker_connections number;
HTTP 模块配置
这里以 nginx-1.22.1 版本给出的默认 nginx.conf 文件作为示例。
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# 重定向错误页面到 /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
# 另一个虚拟主机使用基于IP、名称和端口的配置
server {
listen 8000;
listen somename:8080;
server_name somename alias another.alias;
location / {
root html;
index index.html index.htm;
}
}
# HTTPS server
server {
listen 443 ssl;
server_name localhost;
ssl_certificate cert.pem;
ssl_certificate_key cert.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
}
可以看到平时使用 Nginx 最常用的配置,包含 http 配置块 和其内部的 server 配置块。
listen
# listen
# 可配置于:server
http {
server {
# listen 后可以只加IP地址、端口或主机名
listen [address]:[port] [参数];
# 还可以加其他参数:
# default/default_server 将当前 server 作为默认块,当请求无法匹配主机域名时,选用默认主机
# e.g.
listen 443 default_server;
}
}
listen 配置的其他参数如下:
backlog=[num] | 默认 -1,TCP 中的 backlog 大小 |
rcvbuf=[size] | 监听句柄的 SO_RCVBUF 参数 |
sndbuf=[size] | 监听句柄的 SO_SNDBUF 参数 |
deferred | 若用户发起建立连接请求,并且完成了TCP的三次握手,内核也不会为了这次的连接调度 worker 进程来处理。只有用户真的发送请求数据时(内核已经在网卡中收到请求数据包),内核才会唤醒 worker 进程处理这个连接 |
bind | 绑定当前端口/地址对,如 127.0.0.1:8000。只有同时对一个端口监听多个地址时才会生效 |
ssl | 当前监听的端口上建立的连接必须基于 SSL 协议 |
server_name
# server_name
# 可配置于:server
http {
server {
server_name [name...];
}
}
在开始处理一个 HTTP 请求时,Nginx 会取出 header 中的 Host,与每个 server 中的 server_name 进行匹配,以此决定到底由哪一个 server 块来处理这个请求。有可能一个 Host 与多个 server 块中的 server_name 都匹配,这时就会根据匹配优先级来选择实际处理的 server 块,以下优先级由高到低:
- 字符串完全匹配的 server_name (e.g. www.testweb.com)
- 通配符在前的 server_name (e.g. *.testweb.com)
- 通配符在后的 server_name (e.g. www.testweb.*)
- 使用正则表达式的 server_name (e.g. ^\.testweb\.com$)
如果都不匹配,则会去寻找 default server,或是 listen 端口下的第一个 server。
server_names_hash_bucket_size / server_names_hash_max_size
# server_names_hash_bucket_size / server_names_hash_max_size
# 可配置于:http、server、location
http {
# server_names_hash_bucket_size 32|64|128;
# server_names_hash_max_size 512;
# 配置可在 http、server、location 下
server_names_hash_bucket_size [size];
server_names_hash_max_size [size];
server {
server_names_hash_bucket_size [size];
server_names_hash_max_size [size];
location / {
server_names_hash_bucket_size [size];
server_names_hash_max_size [size];
}
}
}
Nginx 使用散列表来存储 server_name。
server_names_hash_bucket_size 设置了每个散列桶占用的内存大小。
server_names_hash_max_size 影响散列表的冲突率。设置的值越大消耗的内存越多,散列 Key 发生冲突的概率会降低,检索速度也会更快。
server_name_in_redirect
# server_name_in_redirect
# 可配置于:http、server、location
http {
# 配置可在 http、server、location 下
server_name_in_redirect on|off;
server {
server_name_in_redirect on|off;
location / {
server_name_in_redirect on|off;
}
}
}
开启时,在重定向请求时会使用 server_name 里配置的第一个主机名代替原先请求中的 Host 头部,而关闭时,表示在重定向请求时使用请求本身的 Host 头部。
location
# location
# 可配置于:server
http {
server {
# location [=|~|~*|^~|@] /uri/{...}
location / {
}
}
}
具体符号匹配规则如下:
= | 把URI作为字符串,以便与参数中的uri做完全匹配 |
~ | 匹配URI时是字母大小写敏感的 |
~* | 匹配URI时忽略字母大小写问题 |
^~ | 匹配URI时只需要其前半部分与uri参数匹配即可 |
@ | 仅用于Nginx服务内部请求之间的重定向,带有@的location不直接处理用户请求 |
/ | 匹配所有请求 |
root
# root
# 可配置于:http、server、location、if
http {
server {
location /download/ {
root /opt/web/html/;
}
}
}
上述示例中,如果有请求 URI 为 /download/index/test.html, Web 服务器将会返回服务器上的 /opt/web/html/download/index/test.html 文件。
alias
对于请求 URI /conf/nginx.conf, 实际想访问文件 /usr/local/nginx/conf/nginx.conf
# alias
# 可配置于:location
http {
server {
location /conf/ {
alias usr/local/nginx/conf/;
}
# 等同于如下 root 设置
location /conf/ {
root usr/local/nginx/;
}
}
}
使用 alias 时,在 URI 向实际文件路径的映射过程中,已经把 location 后配置的 /conf 这部分字符串丢弃掉,因此,/conf/nginx.conf 请求将根据 alias path 映射为 path/nginx.conf。root 则不然,它会根据完整的 URI 请求来映射,因此,/conf/nginx.conf 请求会根据 root path 映射为 path/conf/nginx.conf。这也是 root 可以放置到 http、server、location 或 if 块中,而 alias 只能放置到 location 块中的原因。
书中解释比较不清晰,我作了示例图如下:

index
# index
# 可配置于:http、server、location
http {
server {
location / {
index [file...];
# e.g.
# default
index index.html;
}
}
}
error_page
# error_page
# 可配置于:http、server、location、if
http {
server {
location / {
error_page [code...] [=|=answer-code] uri|@named_location;
# e.g. 根据返回的错误码重定向到新的 URI
error_page 404 404.html;
error_page 502 503 504 50x.html;
error_page 403 http://example.com/forbidden.html;
error_page 404 = @fetch
# 通过 = 来更改返回的错误码
error_page 404 =200 empty.gif;
error_page 404 =403 forbidden.gif;
# 不指定确切的返回错误码,根据重定向后的实际处理结果决定
error_page 404 = /empty.gif;
# 不修改 URI,让请求重定向到另一个 location
error_page 404 @fallback;
}
location @fallback {
# e.g. 反向代理到 http://backend 去处理
proxy_pass http://backend;
}
}
}
recursive_error_page
# recursive_error_page
# 可配置于:http、server、location
http {
server {
location / {
# 是否允许递归定义 error_page
recursive_error_page on|off;
# e.g.
# default
recursive_error_page off;
}
}
}
try_files
# try_files
# 可配置于:server、location
http {
server {
try_files [path...] uri;
# e.g.
try_files /system/main/tenance.html $uri $uri/index.html $uri.html @other;
# e.g. 可以指定错误码,与 error_page 配合
try_files $uri $uri /error.phpc=404 =404;
location @other {
proxy_pass http://backend;
}
}
}
client_body_in_file_only / client_body_in_single_buffer
# client_body_in_file_only HTTP 包体存储到磁盘文件
# client_body_in_single_buffer HTTP 包体写入到内存 buffer(溢出则存储到磁盘)
# 可配置于:http、server、location
http {
server {
location / {
# default off
client_body_in_file_only on|off;
# default off
client_body_in_single_buffer on|off;
}
}
}
client_header_buffer_size / large_client_header_buffers
# client_header_buffer_size
# large_client_header_buffers
# 可配置于:http、server
http {
server {
# 定义了 Nginx 接收用户请求中 HTTP header 时分配的内存 buffer 大小
client_header_buffer_size [size];
# e.g.
# default
client_header_buffer_size 1K;
# 存储超大 HTTP 头部的内存 buffer 大小
large_client_header_buffers [number] [size];
# e.g.
# default
large_client_header_buffers 48K;
}
}
如果 HTTP 的 header 大小超过了 client_header_buffer_size 定义值,则由 large_client_header_buffers 处理。large_client_header_buffers 定义了 Nginx 接受一个超大 HTTP 头部请求 的 [buffer 个数] 和 [单个 buffer 大小]。HTTP 请求行 和 每个 heaer 的大小不可以超出设定值,请求行和请求头部的总和也不能超过 [buffer 个数]*[单个 buffer 大小]。
client_body_buffer_size / client_body_temp_path
# client_body_buffer_size
# client_body_temp_path
# 可配置于:http、server、location
http {
server {
location / {
# Nginx 接收 HTTP 包体的内存缓冲区大小(由上面的 client_body_in_single_buffer 开启)
client_body_buffer_size [size];
# e.g.
# default
client_body_buffer_size 8K/16K;
# HTTP 包体存放的临时目录
client_body_temp_path dir-path[level1[level2[level3]]];
# default
client_body_temp_path client_body_temp;
# e.g.
client_body_temp_path /opt/nginx/client_temp 1 2;
}
}
}
主要描述一下上述示例中的 client_body_temp_path。在接收 HTTP 包体时,如果包体的大小大于client_body_buffer_size,则会以一个递增的整数命名并存放到 client_body_temp_path 指定的目录中。后面跟着的level1、level2、level3,是为了防止一个目录下的文件数量太多,从而导致性能下降,因此使用了 level 参数,这样可以按照临时文件名最多再加三层目录。
如新上传的 HTTP 包体使用 00000123456 作为临时文件名,则会存放在:
/opt/nginx/client_temp/6/45/00000123456
connection_pool_size / request_pool_size
# connection_pool_size
# request_pool_size
# 可配置于:http、server
http {
server {
# 对每个成功建立的 TCP 连接会预先分配一个内存池,用于指定内存池的初始大小
connection_pool_size [size];
# e.g.
# default
connection_pool_size 256;
# 处理 HTTP 请求时,将会为每个请求都分配一个内存池,用于指定内存池的初始大小
request_pool_size [size];
# e.g.
# default
request_pool_size 4K;
}
}
client_timeout
# client_header_timeout
# client_body_timeout
# send_timeout
# reset_timeout_connection
# 可配置于:http、server、location
http {
server {
location / {
# 读取 HTTP 头部超时时间
# default 60
client_header_timeout [time];
# 读取 HTTP 包体超时时间
# default 60
client_body_timeout [time];
# 发送响应超时时间
# default 60
send_timeout [time];
# 开启后,Nginx 不使用四次握手关闭 TCP 连接,而是直接发送 RST 重置包,直接释放套接字缓存
# default off
reset_timeout_connection on|off;
}
}
}
lingering
# lingering_close
# lingering_time
# lingering_timeout
# 可配置于:http、server、location
http {
server {
location / {
# 关闭用户连接的方式
# always: 关闭连接前必须无条件处理连接上所有用户发送的数据
# off: 关闭连接时完全不管连接上是否已经有准备就绪的来自用户的数据
# on: 一般情况下在关闭连接前都会处理连接上的用户发送的数据
# default on
lingering_close off|on|always;
# 经过 lingering_time 后,Nginx 会关闭连接
# default 30s
lingering_time [time];
# lingering_close 生效情况下
# 在关闭连接前,会检测是否有用户发送的数据到达服务器
# 如果超过 lingering_timeout 时间后还没有数据可读,就直接关闭连接
# 否则在读取完连接缓冲区上的数据并丢弃掉后才会关闭连接
# default 5s
lingering_timeout [time];
}
}
}
keepalive
# keepalive_disable
# keepalive_timeout
# keepalive_requests
# tcp_nodelay
# tcp_nopush
# 可配置于:http、server、location
http {
server {
location / {
# 对指定浏览器禁用 keepalive
# default msie6 safari
keepalive_disable [msie6|safari|none];
# keepalive 超时时间
# default 75
keepalive_timeout [time];
# 长连接上允许承载的请求最大数
# default 100
keepalive_requests n;
# 是否使用 TCP_NODELAY
# default on
tcp_nodelay on|off;
# 打开 tcp_nopush 后,将会在发送响应时把整个响应包头放到一个 TCP 包中发送
# default off
tcp_nopush on|off;
}
}
}
mime
# types 映射
# types_hash_bucket_size
# types_hash_max_size
# 可配置于:http、server、location
# e.g.
types {
text/html html;
text/html conf;
image/gif gif;
image/jpeg jpeg;
}
http {
server {
location / {
default_type [MIME-type];
# default
default_type text/plain;
# 同上述的散列表设计,散列桶占用内存大小
# default 32|64|128
types_hash_bucket_size [size];
# 影响散列表的冲突率
# default 1024
types_hash_max_size [size];
}
}
}
limit_except
# limit_except
# 可配置于:location
http {
server {
location / {
# limit_except 后面指定方法名来限制用户请求
# method 包括: GET、HEAD、POST、PUT、DELETE
# MKCOL、COPY、MOVE、OPTIONS、PROPFIND、PROPPATCH、LOCK、UNLOCK 或者 PATCH
limit_except [method] {
...
}
# e.g. 禁止 GET 和 HEAD 方法
limit_except GET {
allow 192.168.1.0/32;
deny all;
}
}
}
}
client_max_body_size
# client_max_body_size
# 可配置于:http、server、location
http {
server {
location / {
# 限制 Content-Length 所示值的大小,超过则直接返回 413 响应
# default 1m
client_max_body_size [size];
}
}
}
limit
# limit_rate
# limit_rate_after
# 可配置于:http、server、location、if
http {
server {
location / {
# 限制客户端请求每秒传输的字节数
# default 0
limit_rate [speed];
# Nginx 向客户端发送的响应长度超过 limit_rate_after 后才开始限速
# default 1m
limit_rate_after [time];
}
}
}
file
# sendfile
# aio
# directio
# directio_alignment
# open_file_cache
# open_file_cache_errors
# open_file_cache_min_uses
# open_file_cache_valid
# 可配置于:http、server、location
http {
server {
location / {
# 启用 Linux 上的 sendfile 系统调用来发送文件
# default off
sendfile on|off;
# 是否启用内核级别的异步文件I/O(与 sendfile 互斥)
# default off
aio on|off;
# 使用 O_DIRECT 选项去读取文件,缓冲区大小为size,通常对大文件的读取速度有优化作用
# (与 sendfile 互斥)
# default off
directio [size]|off
# 与 directio 配合使用,指定以 directio 方式读取文件时的对齐方式
# 默认 512B,对于高性能文件系统(e.g. XFS)需要设置到 4KB
# default 512
directio_alignment [size];
# 打开文件缓存,在内存中存储{[文件句柄、大小、最后修改时间], [打开过的目录结构], [未到/无权限的文件信息]}
# default off
# max: 在内存中存储元素的最大个数,达到最大限制数量后,将采用 LRU 算法淘汰
# inactive: 指定时间段内没有被访问过的元素将会被淘汰,默认 60s
open_file_cache max=N[inactive=time]|off;
# 是否缓存打开文件错误的信息
# default off
open_file_cache_errors on|off;
# 不被淘汰的最小访问次数
# 与 open_file_cache 中的 inactive 参数配合使用
# inactive 指定时间内,访问(命中)次数超过了 open_file_cache_min_uses 指定的次数,那么将不会被淘汰
# default 1
open_file_cache_min_uses [number];
# 每 60 秒检查一次缓存中的元素是否仍有效
# default 60s
open_file_cache_valid [time];
}
}
}
ignore_invalid_headers / underscores_in_headers
# ignore_invalid_headers
# underscores_in_headers
# 可分配于:http、server
http {
server {
# 忽略不合法的HTTP头部
# default on
ignore_invalid_headers on|off;
# HTTP 头部是否允许下划线(_)
# default off
underscores_in_headers on|off;
}
}
if_modified_since
# if_modified_since
# 可分配于:http、server、location
http {
server {
location / {
# 如何处理 if_modified_since 头部
# default exact
# off: 忽略 if_modified_since 头部
# exact: 将头部时间与返回文件的上次修改时间做精确比较,匹配上则无需返回文件,返回 304 Not Modified
# before: 比 exact 更宽松,只需要文件上次修改时间等于或早于用户请求中的头部时间,就会返回 304
if_modified_since [off|exact|before];
}
}
}
log_not_found / merge_slashes
# log_not_found
# merge_slashes
# 可分配于:http、server、location
http {
server {
location / {
# 文件未找到时是否记录到 error 日志(error.log)
# default on
log_not_found on|off;
# 是否合并相邻的 '/',例如 /test///a.txt 将会合并为 /test/a.txt
# default on
merge_slashes on|off;
}
}
}
dns
# resolver
# resolver_timeout
# 可分配于:http、server、location
http {
server {
location / {
# DNS 解析地址
resolver [address...];
# DNS 解析超时时间
# default 30s
resolver_timeout [time];
}
}
}