Nginx使用总结

liminjun

本文着重介绍Nginx的使用方法,主要包含Nginx进程管理,常用配置和TCP内核参数优化等内容。

Nginx进程管理

  • 可以用向Nginx发送信号的方式管理Nginx进程

    1
    2
    3
    4
    nginx -s reload		#重新加载配置文件,对应信号HUP
    nginx -s reopen #重新写日志,对应信号USR1
    nginx -s stop #关闭nginx,对应信号TERM
    nginx -s quit #优雅退出nginx,对应信号QUIT
  • 配置文件热更新的流程(nginx -s reload)

    1
    2
    3
    4
    nginx能实现配置文件热更新是具有其master和worker的多进程模型,其具体操作步骤如下:
    (1) 当用户输入nginx -s reload命令时,会先读取pid文件获取master进程的pid,然后对master进程发送HUP信号
    (2) master进程在收到HUP信号后,会启动新的worker进程,这些新启动的worker进程加载最新的配置文件,之后会向老的worker进程发送QUIT信号(优雅退出)
    (3) 在完成新老worker进程的更替后,nginx整体对外便实现了配置热加载的功能

Nginx常用配置

  • 调试相关配置
参数名 取值 默认值或示例 描述
daemon on|off daemon on; 是否以守护进程方式启动
master_process on|off master_process on; 是否以master/worker方式工作
error_log /path/file level error_log logs/error.log error; error日志的设置
debug_points stop|abort 是否处理几个特殊的调试点
debug_connection [IP|CIDR] 仅对指定的ip输出debug级别的日志
worker_rlimit_core size 限制coredump文件的大小
working_directory path worker进程的工作目录
1
2
3
4
5
6
debug_connection
这个配置项属于事件类配置,它必须放到events {...}中才能生效
events {
debug_connection 10.224.66.14;
debug_connection 10.224.57.0/24;
}
  • 正常运行的配置项
参数名 取值 默认值或示例 描述
env VAR|VAR=VALUE 定义环境变量
include /path/file include mime.types;
include vhost/*.conf;
嵌入其他配置文件
pid /path/file pid logs/nginx.pid; pid文件的路径
user username [groupname] user nobody nobody; worker进程运行的用户及用户组
worker_rlimit_nofile limit 限制worker进程最大可以打开的句柄数量
worker_rlimit_sigpending limit 限制信号队列
  • 优化性能的配置项
参数名 取值 默认值或示例 描述
worker_processes_number number worker_processes_number 1; 设置worker进程的数量
worker_cpu_affinity cpumask [cpumask…] worker_processes_number 4;
worker_cpu_affinity 1000 0100 0010 0001;
绑定worker进程到指定cpu核心
ssl_engine device ssl硬件加速
timer_resolution time 系统调用gettimeofday的执行频率
work_priority nice work_priority 0; 设置worker进程的nice优先级
  • 事件类配置项
参数名 取值 默认值或示例 描述
accept_mutex [on|off] accept_mutex on; 是否打开accept锁
lock_file /path/file lock_file logs/nginx.lock; lock文件的路径,文件锁
accept_mutex_delay Nms accept_mutex_delay 500ms; accept锁后到真正建立连接的延迟时间
multi_accept [on|off] multi_accept off; 批量建立新连接
use [kqueue|rtsig|epoll|
/dev/poll|select|poll|eventport]
选择事件模型
worker_connections number 每个worker的最大连接数
1
2
3
4
accept_mutex
master进程监听web端口,fork出多个子进程,这些子进程开始同时监听同一个web端口。假如,在某一时刻,所有的worker子进程都休眠且等待新连接的系统调用(epoll_wait),这时有一个用户向服务端发起连接,内核收到TCP的SYN包时,会激活所有的休眠worker子进程,此时只有最先开始执行accept的子进程可以成功建立新连接,而其他worker子进程都会accept失败,这些失败accept失败的子进程被内核唤醒是不必要的,这个现象被称为"惊群"。
通过设置accept_mutex可以保证某一时刻仅能有一个子进程监听web端口(只有调用ngx_trylock_accept_mutex方法后,当前worker进程才会去试着监听web端口),从而解决"惊群"问题。
如关闭accept_mutex,建立TCP连接的耗时会更短,但worker进程之间的负载会非常不均衡。
1
2
accept_mutex_delay
如果一个worker进程试图取accept锁没有取到,它至少等待accept_mutex_delay定义的时间间隔后才能再次试图取锁。
1
2
multi_accept
当事件模型通知有新连接时,尽可能对本次调度中客户端发起的所有TCP请求都建立连接。
  • 静态web服务器相关配置项
参数名 取值 默认值或示例 描述
listen address:port 示例见补充 监听端口
server_name “” 主机名称
server_name_hash_bucket_size size 32|64|128 每个散列桶占用的内存大小
server_name_hash_max_size size 512 影响散列表的冲突率
server_name_in_redirect on|off on 重定向主机名称的处理
location 匹配用户请求中的uri
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
listen
示例:
listen 127.0.0.1:8000;
listen 127.0.0.1;
listen 8000;
listen *:8000;
listen localhost:8000;

ipv6:
listen [::]:8000;
listen [fe80::1];
listen [:::a8c9:1234]:80;

增加参数:
listen 443 default_server ssl;
listen 127.0.0.1 default_server accept_filter=dataready backlog=1024;

参数描述:
default: 将所在的server块作为整个web服务的默认server块。如果没有设置那么将会以nginx.conf中找到的第一个server块作为默认的server块。当一个请求无法匹配配置文件中的所有主机的域名时,就会选用默认的虚拟主机。
default_server: 同上。
backlog=num: 表示TCP中backlog队列的大小。默认为-1,表示不予设置。在TCP建立三次握手过程中,进程还没有开始处理监听句柄,这是backlog队列会放置这些新连接。如果backlog队列已满,还有新的客户端试图通过三次握手建立TCP连接,这时客户端将会建立连接失败。
rcvbuf=size: 设置监听句柄的SO_RCVBUF参数。
sndbuf=size: 设置监听句柄的SO_SNDBUF参数。
accept_filter: 设置accept过滤器,只对FreeBSD系统有用。
deferred: 在设置该参数后,若用户发起建立连接请求,并完成了TCP的三次握手,内核也不会为了这次的连接调度worker进程来处理,只有用户真的发送请求数据时(内核已在网卡中收到请求数据包),内核才会唤醒worker进程处理这个连接。这个参数适用于大并发的情况,它减轻了worker进程的负担,当请求数据来临时,worker进程才会开始处理这个连接。
bind: 绑定当前端口/地址对,只有同时对一个端口监听多个地址时才会生效。
ssl: 在当前建立的端口上建立的连接必须基于ssl协议。
1
2
3
4
5
6
7
8
9
10
server_name
server_name后可以跟多个主机名称,在处理一个http请求时,Nginx会取出header头中的Host,与每个server中的server_name进行匹配,以此决定到底由哪个server块来处理这个请求。匹配的优先级:
1.首先选择所有字符串完全匹配的server_name
2.其次选择通配符在前面的server_name
3.再次选择通配符在后面的server_name
4.最后选择使用正则表达式匹配的server_name,如~^\.test\.com$
如果Host与所有的server_name都不匹配,这时将会按照下面的顺序处理server块:
1.优先选择在liten配置项后加入[default|default_server]的server块
2.找到匹配listen端口的第一个server块
如果server_name后面跟着空字符串(如server_name "";),那么表示匹配没有Host这个http头部的请求。
1
2
server_name_in_redirect
当打开时,表示在重定向请求时会使用server_name里配置的第一个主机名代替原先请求中的Host头部。
1
2
3
4
5
6
7
8
9
location
匹配规则:
= 完全匹配
~ 大小写敏感
~* 忽略大小写
^~ 表示只要前半部分匹配即可
@ 表示仅用于Nginx内部请求之间的重定向,带@的location不直接处理用户的请求,例如 error_page, try_files
优先级:
= 高于 ^~ 高于 ~* 等于 ~ 高于 /
  • 文件路径的定义
参数名 取值 默认值或示例 描述
root path /var/www/html 资源路径
alias path /var/www/html 资源路径
index file… /index.html /index.php 配置首页
error_page [code] uri 404 /404.html 根据http返回码重定向页面
recursive_error_pages [on|off] off 是否允许递归使用error_page
try_files path1 [path2…] uri test.html 逐个尝试path
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
root和alias的区别
location /conf {
root /usr/local/nginx;
}
location /conf {
alias /usr/local/nginx;
}
请求uri为/conf/nginx.conf
对于root会访问本地文件/usr/local/nginx/conf/nginx.conf
对于alias会访问本地文件/usr/local/nginx/nginx.conf

alias支持添加正则表达式
location ~ ^/test/(\w+)\.(\w+)$ {
alias /usr/local/nginx/$2/$1.$2;
}
在访问/test/nginx.conf时,nginx会返回/usr/local/nginx/conf/nginx.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
error_page
当对某个请求返回错误码时,如果匹配上了error_page中设置的code,则重定向到新的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
重定向后,http错误和之前的相同,可通过"="来更改返回的错误码,例如:
error_page 404 =200 /empty.gif
也可以根据重定向后的实际处理的结果设置错误码:
error_page 404 = /empty.gif

重定向到其他location
location / {
error_page 404 @fallback;
}
location @fallback {
proxy_pass http://backend;
}
1
2
3
4
5
6
7
8
9
10
try_files
try_files后要跟若干路径,如path1 path2,而且最后必须要有uri参数,该配置会顺序访问每个path,如果可以有效地读取,就直接返回这个path对应的文件结束请求,否则继续向下访问。如果所有的path都找不到有效的文件,就重定向到最后的参数uri上。因此,最后这个uri必须存在,而且它应该时可以有效重定向的。例如:
try_files /system/maintenance.html $uri $uri/index.html $uri.html @other
location @other {
proxy_pass http://backend;
}
也可通过错误码和error_page配合使用,例如:
location / {
try_files $uri $uri/ =404
}
  • 内存及磁盘资源的分配
参数名 取值 默认值或示例 描述
client_body_in_file_only on|clean|off off HTTP包体只存储到磁盘文件中
client_body_in_single_buffer on|off off HTTP包体尽量写入到一个内存buffer中
client_header_buffer_size size 1k 存储HTTP头部的内存buffer大小
large_client_header_buffers number size 4 8k 存储超大HTTP头部的内存buffer大小
client_body_buffer_size size 8k/16k 存储HTTP包体的内存buffer大小
client_body_temp_path dir-path client_body_temp HTTP包体的临时存放目录
connection_pool_size size 256 连接池大小
request_pool_size size 4k 请求内存池大小
1
2
client_body_in_single_buffer
用户请求中的HTTP包体一律存储到内存的buffer中,但是如果HTTP包体大小超过client_body_buffer_size设置的值,包体还是会写入到磁盘文件中
  • 网络连接设置
参数名 取值 默认值或示例 描述
client_header_timeout time 60 读取HTTP头部的超时时间
client_body_timeout time 60 读取HTTP包体的超时时间
send_timeout time 60 发送响应的超时时间
reset_timeout_connection on|off off 发送RST包来直接重置连接
lingering_close off|on|always on Nginx关闭用户连接的方式
lingering_time time 30
lingering_timeout time 5s
keepalive_disable [msie6|safari|none] msie6 safari 对某些浏览器禁用keepalive功能
keepalive time 75 keepalive超时时间
keepalive_requests num 100 keepalive连接上允许的最大请求数
tcp_nodelay on|off on keepalive连接是否使用TCP_NODELAY选项
tcp_nopush on|off off 是否带TCP_CORK选项
1
2
reset_timeout_connection
这个选项打开后,Nginx会在某个连接超时后,不是使用正常的四次挥手关闭TCP连接,而是直接向用户发送RST重置包,不再等待用的应答。相比正常关闭的方式,它使得服务器避免产生许多处于FIN_WAIT_1,FIN_WAIT_2,TIME_WAIT状态的连接
1
2
3
4
5
6
7
8
9
lingering_close
该配置控制Nginx关闭用户连接的方式
always: 关闭用户连接前必须无条件地处理连接上所有用户发送的数据
off: 表示关闭连接时完全不管连接上是否已经有准备就绪的来着用户的数据
on: 中间值,一般情况下在关闭连接前都会处理连接上的用户数据,除了有些情况下在业务上认定这之后的数据是不必要的

lingering_close启用后,对上传大文件很有用,当用户请求的Content-Length大于max_client_body_size配置时,Nginx服务会立刻项用户返回413(Request entity too large)响应。但是,很多客户端可能不管413返回值,仍然持续不断地上传HTTP body,这时,经过lingering_time设置的时间后,Nginx将不管用户是否仍在上传,都会把连接关闭掉

在关闭连接前,会检测是否有用户发送的数据到达服务器,如果超过lingering_timeout时间后还没有数据可读,就会直接关闭连接;否则,必须在读取完连接缓冲区上的数据并丢弃掉后才会关闭连接
  • MIME类型的设置
参数名 取值 默认值或示例 描述
types …{…} MIME type与文件扩展的映射
default_type MIME-type text/plain 当找不到映射时使用的默认MIME type
types_hash_bucket_size size 32|64|128 查找MIME type散列表桶的大小
types_hash_max_size size 1024 查找MIME type散列表桶的数量
  • 对客户端请求的限制
参数名 取值 默认值或示例 描述
limit_except … {…} 按HTTP方法名限制用户请求
client_max_body_size size 1m HTTP请求包体的最大值
limit_rate speed 0 对请求的限速
limit_rate_after time 1m 表示发送一定大小后再限速
1
2
3
4
5
6
limit_except
limit_except GET {
allow 192.168.1.0/32;
deny all;
}
方法名取值包括:GET、HEAD、POST、PUT、DELETE、MKCOL、COPY、MOVE、OPTIONS、PROPFIND、PROPPATCH、LOCK、UNLOCK、PATCH等
  • 文件操作的优化
参数名 取值 默认值或示例 描述
sendfile on|off off sendfile系统调用
aio on|off off AIO系统调用,与sendfile互斥
directio size|off off 是否使用O_DIRECT选项读取文件
对大文件读取速度有优化,与sendfile互斥
directio_alignment size 512 directio读取文件时的对齐方式
通常512足够,对于高性能文件系统如
XFS文件系统可设置到4KB
open_file_cache max=num [inactive=time] off off 打开文件缓存,LRU算法淘汰
open_file_cache_errors on|off off 是否缓存打开文件的错误信息
open_file_cache_min_use num 1 不被淘汰的最小访问次数
open_file_cache_valid time 60s 检验缓存中元素有效性的频率
  • 对客户端请求的特殊处理
参数名 取值 默认值或示例 描述
ignore_invalid_headers on|off on 忽略不合法的HTTP头部
underscores_in_headers on|off off HTTP头部是否允许下划线
if_modified_since off|exact|before exact 对If-Modified-Since头部的处理策略
log_not_found on|off on 文件未找到时是否记录到error日志
merge_slashes on|off on 是否合并相邻的”/“
resolver address 8.8.8.8 114.114.114.114 设置DNS解析服务器地址
resolver_timeout time 30s DNS解析的超时时间
server_tokens on|off on 请求出错时是否在响应中标明Nginx版本
1
2
3
4
5
6
if_modified_since
出于性能考虑,Web浏览器一般会在客户端本地缓存一些文件,并存储当时获取的时间。这样下次向Web服务器获取缓存过的资源时,就可以用If-Modified-Since头部把上次获取的时间捎带上,而if_modified_since将根据后面的参数决定如何处理If-Modified-Since头部
相关参数说明:
off: 忽略If-Modified-Since头部,正常返回文件内容,响应码200
exact: 当If-Modified-Since与文件的上次修改时间精准匹配时返回304(Not Modified),表示没有修改,浏览器直接读取缓存,否则正常返回文件内容,返回200
before: 当文件的上次修改时间比If-Modified-Since的时间早时返回304(Not Modified),表示没有修改,浏览器直接读取缓存,否则正常返回文件内容,返回200

在修改nginx配置文件和打日志的过程中可以带入一些变量,以下列出ngx_http_core_module模块提供的一些常用变量:

参数名 解释
$arg_PARAMETER HTTP请求中某个参数的值,如/index.html?size=100,可以用$arg_size取得100这个值
$args HTTP请求中的完整参数。例如,在请求/index.html?_w=120&_h=120中,$args表示字符串w=120&h=120
$binary_remote_addr 二进制格式的客户端地址。例如: \x0A\xE0B\x0E
$body_bytes_sent 表示在向客户端发送的http响应中,包体部分的字节数
$content_length 表示客户端请求头部中的Content-Length字段
$content_type 表示客户端请求头部中的Content-type字段
$cookie_COOKIE 表示在客户端请求头部中的的cookie字段
$document_root 表示当前请求所使用的root配置项的值
$uri 表示当前请求的URI,不带任何参数
$document_uri 与$uri含义相同
$request_uri 表示客户端发来的原始请求URI,带完整的参数。$uri和$document_uri未必是用户的原始请求,在内部重定向后可能是重定向后的URI,而$request_uri永远不会改变,始终是客户端的原始URI
$host 表示客户端请求头部中的Host字段,如果Host字段不存在,则以实际处理的server(虚拟主机)名称代替。如果Host字段中带有端口,如IP:PORT,那么$host是去掉端口的,它的值为IP。$host是全小写的。这些特性与http_HEADER中的http_host不同。http_host只是”忠实”地提取出Host头部对应的值
$hostname 表示Nginx所在机器的名称,与gethostbyname调用的返回值相同
$http_HEADER 表示当前HTTP请求中相应头部的值。HEADER名称全小写。例如,用$http_host表示请求中Host头部对应的值
$sent_http_HEADER 表示返回客户端的HTTP响应中相应头部的值。HEADER名称全小写。例如,用$sent_http_content_type表示响应中Content-Type头部对应的值
$is_args 表示请求中的URI是否带参数,如果带参数,$is_args值为?,如果不带参数,则是空字符串
$limit_rate 表示当前连接的限速是多少,0表示无限速
$nginx_version 表示当前Nginx的版本号,如1.0.14
$query_string 请求URI中的参数,与$args相同,然后$query_string是只读的不会改变
$remote_addr 表示客户端的地址
$remote_port 表示客户端连接使用的端口
$remote_user 表示使用Auth Basic Module时定义的用户名
$request_filename 表示用户请求中URI经过root或alias转换后的文件路径
$request_body 表示HTTP请求中的包体,该参数只在proxy_pass或fastcgi_pass中有意义
$request_body_file 表示HTTP请求中包体存储的临时文件名
$request_completion 当请求已经全部完成时,其值为”ok”。若没有完成,就要返回客户端,则其值为空字符串;或者在断点续传等情况下使用HTTP range访问的并不是文件的最后一块,那么其值也是空字符串
$request_method 表示HTTP请求的方法名,如GET、PUT、POST等
$scheme 表示HTTP scheme,如在请求https://nginx.org 中表示https
$server_addr 表示服务器地址
$server_name 表示服务器名称
$server_port 表示服务器端口
$server_protocol 表示服务器向客户端发送响应的协议,如HTTP/1.1或HTTP/1.0

Linux网络参数调优

由于默认的 Linux内核参数考虑的是最通用的场景,这明显不符合用于支持高并发访问的Web服务器的定义,所以需要修改 Linux内核参数,使得 Nginx可以拥有更高的性能。

在优化内核时,可以做的事情很多,不过,我们通常会根据业务特点来进行调整,当Nginx作为静态Web内容服务器、反向代理服务器或是提供图片缩略图功能(实时压缩图片)的服务器时,其内核参数的调整都是不同的。这里只针对最通用的、使 Nginx支持更多并发请求的TCP网络参数做简单说明。

首先,需要修改/etc/sysctl. conf来更改内核参数。例如,最常用的配置:

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
29
30
#这个参数表示进程(比如一个worker进程)可以同时打开的最大句柄数,这个参数直接限制最大并发连接数,需根据实际情况配置
fs.file-max = 999999
#这个参数设置为1,表示允许将 TIME-WAIT状态的socket重新用于新的TCP连接,这对于服务器来说很有意义,因为服务器上总会有大量TIME-WAIT状态的连接
net.ipv4.tcp_tw_reuse = 1
#这个参数表示当keepalive启用时,TCP发送keepalive消息的频度。默认是2小时,若将其设置得小一些,可以更快地清理无效的连接。
net.ipv4.tcp_keepalive_time = 600
#这个参数表示当服务器主动关闭连接时,socket保持在FIN-WAIT-2状态的最大时间
net.ipv4.tcp_fin_timeout = 30
#这个参数表示操作系统允许TIME-WAIT套接字数量的最大值,如果超过这个数字,TIME-WAIT套接字将立刻被清除并打印警告信息。该参数默从为180000,过多的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命令,使上述修改生效。

  • Title: Nginx使用总结
  • Author: liminjun
  • Created at: 2022-03-13 15:07:10
  • Updated at: 2023-05-15 10:38:23
  • Link: https://olldbg.github.io/2022/03/13/Nginx使用总结/
  • License: This work is licensed under CC BY-NC-SA 4.0.