6、nginx通用配置
1、nginx进程之间的关系
部署Nginx时都是使用一个
master
进程来管理多个worker
进程,一般情况下,worker
进程的数量与服务器上的CPU核心数相等。worker 进程之间通过共享内存、原子操作等一些进程间通信机制来实现负载均衡等功能
2、单进程nginx环境使用
- 由于 master 进程不会对用户请求提供服务,只用于管理真正提供服务的 worker 进程。所以 master 进程可以是唯一的,它仅专注于自己的管理工作,为管理员提供
命令行
服务,包括诸如启动服务、停止服务、重载配置文件、平滑升级程序等。 - master 进程需要拥有较大的权限,例如,通常会利用 root 用户启动 master 进程。worker进程的权限要小于或等于master进程,这样 master 进程才可以完全地管理 worker 进程。当任意一个 worker 进程出现错误从而导致 coredump 时,master 进程会立刻启动新的 worker 进程继续服务。
- 多个 worker 进程处理互联网请求不但可以提高服务的健壮性 ( 一个 worker 进程出错后,其他 worker 进程仍然可以正常提供服务),最重要的是,实现微观上真正的多核并发处理。因此,用一个进程 (master 进程) 来处理互联网请求肯定是不合适的。
- 为什么要把 worker 进程数量设置得与CPU核心数量一致呢?这正是 Nginx 与 Apache 服务器的不同之处。在 Apache 上每个进程在一个时刻只处理一个请求,因此,如果希望 Web 服务器拥有并发处理的请求数更多,就要把 Apache 的进程或线程数设置得更多,通常会达到一台服务器拥有几百个工作进程,这样大量的进程间切换将带来无谓的系统资源消耗。而 Nginx 则不然,一个 worker 进程可以同时处理的请求数只受限于内存大小,而且在架构设计上,不同的 worker 进程之间处理并发请求时几平没有同步锁的限制,worker进程通常不会进入睡眠状态,因此,当 Nginx 上的进程数与 CPU 核心数相等时(最好每一个 worker 进程都绑定特定的 CPU 核心),进程间切换的代价是最小的。
如果服务器的 CPU 核心数为8,那么就需要配置8个 worker进程
3、Nginx配置的通用语法
3.1 块配置
块配置项由一个块配置项名和一对大括号组成。具体示例如下:
events {
...
}
http {
upstream backend {
server 127.0.0.1:8080;
}
gzip on;
server {
...
location /webstatic {
gzip off;
}
}
}
- 上面代码段中的
events
、http
、server
、location
、upstream
等都是块配置项 - 块配置项之后是否可以加上
location /webstatic {...}
参数,取决于解析这个块配置项的模块 - 块配置项一定会用大括号把一系列所属的配置项全包含进来,表示大括号内的配置项同时生效。
- 块配置项可以嵌套。内层块直接继承外层块,例如,上例中
server
块里的任意配置都是基于http
块里的已有配置的。 - 当内外层块中的配置与外层块发生冲突时,究竟是以内层块还是外层块的配置为准,取决于解析这个配置项的模块,例如,上例在
http
模块中已经打开了gzip on;
,但其下的location /webstatic
又把gzip
关闭了:gzip off;
,最终,在/webstatic
的处理模块中,gzip 模块是按照gzip off
来处理请求的。
3.2 配置项基本语法说明
nginx 最基本的配置项语法格式如下:
配置项名 配置项值 1 配置项值 2 ··· ;
- 在行首的是配置项名,这些配置项名必须是 Nginx 的某一个模块想要处理的,否则 Nginx 会认为配置文件出现了非法的配置项名。
- 配置项名输入结束后,以空格作为分隔符。
- 配置项值,可以是数字、字符串、正则表达式。
- 一个配置项既可以只有一个值,也可以包含多个值,一个配置项对应的值究竟有多少个,取决于解析这个配置项的模块。
- 配置项值之间由空格符来分隔。
- 必须根据某 Nginx 模块对一个配置项的约定来更改配置项。
- 每行配置的结尾需要加上分号。
- 如果配置项值中包括语法符号,比如空格符,那么需要使用单引号或双引号括住配置项值,否则 Nginx 会报语法错误。例如:
log_format_main '$remote_addr - $remote_user [$time_local] "$request" '
3.3 配置项的注释
如果有一个配置项暂时需要注释掉,那么可以加
#
注释掉这一行配置。例如:# pid logs/nginx.pid;
3.4 配置项的单位
大部分模块遵循一些通用的规定,如: 指定空间大小时不用每次都定义到字节、指定时间时不用精确到毫秒。
- 当指定空间大小时,可以使用的单位包括:K或者k千字节 (KiloByte,KB)、M或者m兆字节(MegaByte,MB)。例如:
gzip_buffers 4 8k;
client_max_body_size 64M;
- 当指定时间时,可以使用的单位包括:ms (毫秒)、s(秒)、m(分钟)、h(小时)、d(天)、w(周,包含7天)、M (月包含30天)、y (年,包含 365 天)。例如:
expires 10y;
proxy_read_timeout 600;
client_body_timeout 2m;
3.5 在配置中使用变量
有些模块允许在配置项中使用变量,如在日志记录部分,具体示例如下:
'log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
remote_addr
是一个变量,使用它的时候前面要加上$符号。需要注意的是,这种变量只有少数模块支持,并不是通用的。- 许多模块在解析请求时都会提供多个变量(如http core module、 http proxy module 、http upstream module等),以使其他模块的配置可以即时使用。学习某个模块提供的配置说明时可以关注它是否提供变量。
4、Nginx服务的基本配置
4.1 配置项分类
- 用于调试、定位问题的配置项。
- 正常运行的必备配置项。
- 优化性能的配置项。
- 事件类配置项(有些事件类配置项归纳到优化性能类,这是因为它们虽然也属于
events{}
块,但作用是优化性能)。
4.2 用于调试进程和定位问题的配置项
- 是否以守护进程方式运行 Nginx
语法: daemon on | off;
默认; daemon on;
- 守护进程 (daemon)是脱离终端并且在后台运行的进程。它脱离终端是为了避免进程执行过程中的信息在任何终端上显示,这样一来,进程也不会被任何终端所产生的信息所打断。Nginx毫无疑问是一个需要以守护进程方式运行的服务,因此,默认都是以这种方式运行的。
- Nginx 提供了关闭守护进程的模式,之所以提供这种模式,是为了方便跟踪调试 Nginx,毕竟用 gdb 调试进程时最烦的就是如何继续跟进
fork
出的子进程了。
- 是否以master/worker 方式工作
语法:master_process on|off;
默认: master_process on;
- Nginx是以一个 master 进程管理多个 worker 进程的方式运行的,几乎所有 Nginx 都以这种方式工作。与daemon配置相同,提供 master process 配置也是为了方便跟踪调试Nginx。
- 如果用off关闭了master_process 方式,就不会 fork 出 worker 子进程来处理请求,而是用 master 进程自身来处理请求。
- error日志的设置
语法:error_log /path/file level;
默认: error_log logs/error.log error;
- error日志是定位Nginx问题的最佳工具,可以根据自己的需求设置error日志的路径和级别。
/path/file
参数可以是一个具体的文件,例如,默认是 logs/error.log 文件,最好将它放到一个磁盘空间足够大的位置/path/file
也可以是/dev/null
,这样就不会输出任何日志了,这也是关闭 error 日志的唯一手段/path/file
也可以是stderr
,这样日志会输出到标准错误文件中。- level是日志的输出级别,取值范围是
debug
、info
、notice
、warn
、error
、crit
、alert
、emerg
,从左至右级别依次增大。当设定为一个级别时,大于或等于该级别的日志都会被输出到/path/file
文中,小于该级别的日志则不会输出。例如,当设定为error
级别时,error
、crit
、alert
、emerg
级别的日志都会输出。 - 如果设定的日志级别是
debug
,则会输出所有的日志,这样数据量会很大,需要预先确保/path/file
所在磁盘有足够的磁盘空间。
注意如果日志级别设定到 debug,必须在 configure 时加入 --with-debug 配置项。
- 是否处理几个特殊的调试点
语法: debug_points [stop|abort]
- 这个配置项是用来帮助用户跟踪调试 Nginx的。它接受两个参数: stop 和abort。
- Nginx 在一些关键的错误逻辑中设置了调试点。如果设置了debug _points为stop,那么Nginx的代码执行到这些调试点时就会发出
SIGSTOP
信号以用于调试。如果 debug_points 设置为 abort,则会产生一个coredump 文件,可以使用gdb 来查看Nginx当时的各种信息。通常不会使用这个配置项。
- 仅对指定的客户端输出 debug 级别的日志
语法: debug_connection [IP|CIDR]
- 这个配置项实际上属于事件类配置,因此,它必须放在 events {} 中才有效。它的值可以是 IP 地址或 CIDR地址,例如:
events {
debug_connection 10.224.66.14;
debug_connection 10.224.57.0/24
}
- 仅仅来自以上IP 地址的请求才会输出 debug级别的日志,其他请求仍然沿用error_log中配置的日志级别
注意 使用debug_connection 前,需确保在执行configure 时已经加入了--with-debug参数,否则不会生效。
- 限制 coredump 核心转储文件的大小
语法:worker_rlimit_core_size;
- 在 Linux 系统中,当进程发生错误或收到信号而终止时,系统会将进程执行时的内存内容(核心映像)写入一个文件 (core 文件),以作为调试之用,这就是所谓的核心转储 (coredumps)。
- 当Nginx进出现一些非法操作(如内存界)导致进直接被操作系统强制结束时,会生成核心转储 core 文件,可以从 core 文件获取当时的堆栈、寄存器等信息,从而帮助我们定位问题。但这种 core 文中的许多信息不一定是用户需要的,如果不加以限制,那么可能一个 core 文件会达到几GB,这样随便 coredumps 几次就会把磁盘占满,引发严重问题。通过 worker_rlimit_core 配置可以限制core 文件的大小,从而有效帮助用户定位问题
- 指定 coredump 文件生成目录
语法:working_directory path;
- worker 进程的工作目录。这个配置项的唯一用途就是设置 coredump 文件所放置的目录,协助定位问题。因此,需确保 worker 进程有权限向 working_directory指定的目录中写入文件。
4.3 正常运行的配置项
- 定义环境变量
语法:env VAR | VAR=VALUE
- 这个配置项可以让用户直接设置操作系统上的环境变量。例如:
env TESTPATH=/tmp/;
- 嵌入其他配置文件
语法:include /path/file;
- include 配置项可以将其他配置文件嵌入到当前的 nginx.conf文件中,它的参数既可以是绝对路径,也可以是相对路径(相对于 Nginx 的配置目录,即nginx.conf 所在的目录),例如:
include mime.types;
include vhost/*.conf;
- 可以看到,参数的值可以是一个明确的文件名,也可以是含有通配符 * 的文件名,同时可以一次嵌入多个配置文件。
- pid文件的路径
语法:pid path/file;
默认: pid logs/nginx.pid;
- 保存master进程ID的pid文存放路径。默认与 configure 执行时的参数
--pid-path
所指定的路径是相同的, - 可以随时修改,但应确保 Nginx 有权在相应的目标中创建 pid 文件,该文件直接影响 Nginx 是否可以运行。
- Nginx worker 进程运行的用户及用户组
语法:user username [groupname];
默认: user nobody nobody;
- user 用于设置 master 进程启动后,fork 出的 worker 进程运行在哪个用户和用户组下。当按照
user username;
设置时,用户组名与用户名相同。 - 若用户在 configure 命令执行时使用了参数
--user=username
和--group=groupname
,此时nginx.conf
将使用参数中指定的用户和用户组。
- 指定Nginx worker 进程可以打开的最大句柄描述符个数
语法: worker_rlimit_nofile_limit;
- 设置一个 worker 进程可以打开的最大文件句柄数
- 限制队列信号
语法: worker_rlimit_sigpending limit;
- 设置每个用户发往 Nginx 的信号队列的大小。也就是说,当某个用户的信号队列满了,这个用户再发送的信号量会被丢掉
4.4 优化性能的配置项
- Nginx worker 进程个数
语法: worker_processes number;
默认: worker_processes 1;
- 在master/worker 运行方式下,定义worker 进程的个数。
- 每个 worker 进程都是单线程的进程,它们会调用各个模块以实现多种多样的功能。如果这些模块确认不会出现阻塞式的调用,那么,有多少 CPU 内核就应该配置多少个进程;反之,如果有可能出现阻塞式调用,那么需要配置稍多一些的 worker 进程。
- 如果业务方面会致使用户请求大量读取本地磁盘上的静态资源文件,而且服务器上的内存较小,以至于大部分的请求访问静态资源文件时都必须读取磁盘(磁头的寻址是缓慢的),而不是内存中的磁盘缓存,那么磁盘I/0 调用可能会阻塞住 worker 进程少量时间进而导致服务整体性能下降。
- 多 worker 进程可以充分利用多核系统架构,但若 worker 进程的数量多于CPU内核数那么会增大进程间切换带来的消耗 (Linux 是抢占式内核)。一般情况下,用户要配置与CPU内核数相等的worker进程,并且使用下面的worker_cpu_affinity配置来定CPU内核。
- 绑定Nginx worker 进程到指定的CPU内核
语法: worker_cpu_affinity cpumask [cpumask....]
- 为什么要绑定 worker 进程到指定的CPU内核呢?假定每一个 worker 进程都是非常繁忙的,如果多个 worker 进程都在抢同一个 CPU,那么这就会出现同步问题。反之,如果每一个 worker 进程都独享一个 CPU,就在内核的调度策略上实现了完全的并发。例如,如果有4颗CPU内核,就可以进行如下配置:
worker_processes 4;
worker_cpu_affinity 1000 0100 0010 0001;
注意 worker _cpu_affinity 配置仅对 Linux 操作系统有效。Linux 操作系统使用sched_setaffinity()系统调用实现这个功能。
- SSL硬件加速
语法:ssl_engine device;
- 如果服务器上有 SSL 硬加速设备,那么就可以进行配置以加快 SSL 协议的处理速度。用户可以使用OpenSSL提供的命今来查看是否有 SSL 硬件加速设备:
openssl engine -t
- 系统调用gettimeofday的执行频率
语法: timer_resolution t;
- 默认情况下,每次内核的事件调用(如epol1、select、poll、kqueue 等)返回时,都会执行一次 gettimeofday,实现用内核的时钟来更新Nginx中的缓存时钟。
- 在早期的 Linux内核中,gettimeofday的执行代价不小,因为中间有一次内核态到用户态的内存复制。当需要降低gettimeofday 的调用频率时,可以使用 timer_resolution 配置。例如
timer_resolution 100ms;
表示至少每100ms 才调用一次 gettimeofday。
- Nginx worker 进程优先级设置
语法:worker_priority nice;
默认; worker_priority 0;
- 在Linux或其他类UNIX操作系统中,当许多进程都处于可执行状态时,将按照所有进程的优先级来决定本次内核选择哪一个进程执行。
- 进程所分配的 CPU 时间片大小也与进程优先级相关,优先级越高,进程分配到的时间片也就越大(例如,在默认配置下,最小的时间片只有 5ms,最大的时间片则有 800ms)。这样,优先级高的进程会占有更多的系统资源。
- 优先级由静态优先级和内核根据进程执行情况所做的动态调整(目前只有 的调整共同决定。nice 值是进程的静态优先级,它的取值范围是 -20 ~ +19,-20 是最高优先级+19 是最低优先级。因此,如果用户希望 Nginx 占有更多的系统资源,那么可以把 nice 值配置得更小一些,但不建议比内核进程的 nice值(通常为-5)还要小。
4.5 事件类配置项
- 是否打开 accept 锁
语法: accept_mutex [on|off]
默认: accept_mutex on;
- accept_mutex是Nginx的负载均衡锁, accept mutex 这把锁可以让多个 worker 进程轮流地、序列化地与新的客户端建立 TCP 连接。
- 当某一个 worker 进程建立的连接数量达到 worker_connections 配置的最大连接数的
7/8
时,会大大地减小该 worker 进程试图建立新TCP 连接的机会,以此实现所有 worker 进程之上处理的客户端请求数尽量接近。 - accept锁默认是打开的,如果关闭它,那么建立TCP 连接的耗时会更短,但 worker 进程之间的负载会非常不均衡,因此不建议关闭它。
- lock 文件的路径
语法: lock_file path/file;
默认: lock_file logs/nginx.lock;
- accept锁可能需要这个 lock 文件,如果 accept 锁关闭,lock_file 配置完全不生效。
- 如果打开了accept锁,并且由于编译程序、操作系统架构等因素导致 Nginx 不支持原子锁,这时才会用文件锁实现 accept 锁,这样 lock_file 指定的lock文件才会生效
- 使用accept 锁后到真正建立连接之间的延迟时间
语法: accept_mutex_delay Nms;
默认: accept_mutex_delay 500ms;
- 在使用accept锁后,同一时间只有一个 worker 进程能够取到accept锁。这个accept 锁不是阻塞锁,如果取不到会立刻返回。
- 如果有一个 worker 进程试图取 accept 锁而没有取到它至少要等accept_mutex_delay 定义的时间间隔后才能再次试图取锁
- 批量建立新连接
语法: multi_accept [on|off];
默认: multi_accept off;
- 当事件模型通知有新连接时,尽可能地对本次调度中客户端发起的所有 TCP 请求都建立连接。
- 选择事件模型
语法: use [ kqueue|rtsig|epoll|/dev/poll|select|poll|eventport ]
默认: Nginx会自动使用最适合的事件模型。
- 对于Linux 操作系统来说,可供选择的事件驱动模型有 poll、select、epoll三种。epoll当然是性能最高的一种.
- 每个worker的最大连接数
语法:worker_connections number:
- 定义每个 worker 进程可以同时处理的最大连接数
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署