Nginx的配置
运行中Nginx进程间的关系
# 为什么产品环境下安装master-worker方式配置同时启动多个进程?
- master进程不会对用户提供服务,只用于管理真正提供服务的worker进程,所以master进程可以是唯一的,为管理员 提供命令行服务,如启停、重载配置文件、平滑升级程序等。
master拥有的权限相对worker要大,当任意一个worker进程出现错误,master进程会立刻启动新的worker进程继续服务。
- 多个worker进程处理请求不但可以提供服务的健壮性,还可以充分利用常见的SMP多核架构,实现微观上真正的多核并发处理。
用一个master处理请求肯定是不合适的,将worker进程数量设置与CPU核数一致,真是Nginx与Apache服务器不同之处。
在Apache上每个进程在一个时刻只处理一个请求,因此,如果希望web服务器拥有并发处理的请求数更多,就要把Apache进程或线程数设置得更多,这样大量进程切换会无谓的消耗系统资源。
而Ngnix一个worker进程可以同时处理的请求数只受限于内存大小,而且在架构设计上,不同的worker进程之间处理并发请求时几乎没有同步锁的限制。,worker进程通常不会进入睡眠状态。因此,Nginx上的进程数与CPU核心数相等时,进程间切换的代价是最小的。
1.Nginx配置通用语法
# 块配置项:由一个块配置项名和一对大括号组成。
server {
...
}
# 配置项的语法格式
配置项名 配置项值1 配置项值2 ...;
access_log logs/access.log main buffer=32k;
说明:
1.行首是配置项名,配置项名必须是Nginx的某一个模块想要处理的,否则视为非法配置项名。
2.配置项名输入后,将以空格作为分隔符。
3.配置项值可以是数字,字符串或正则表达式。
4.一个配置项可以有一个或多个配置项值,一个配置项的配置项值有多少个取决于解析这个配置项的模块。
5.配置项值之间也是使用空格作为分隔符。
6.每行配置的结尾需要加上分号。
7.如果配置项值中包括语法符号,比如空格需要使用单引号或双引号包裹,否则Nginx会报语法错误。
2.配置项注释
# 使用#注释某一行配置
#pid logs/nginx.pid;
3.配置项的单位
# 大部分模块遵循一些通用规定,如指定空间大小不用每次都精确到字节;指定时间不用精确到毫秒。
- 当指定空间大小时,可使用单位:
- K或k千字节(KB)
- M或m兆字节(MB)
- 当指定时间时,可使用单位:
- ms(毫秒)
- s(秒)
- m(分钟)
- h(小时)
- d(天)
- w(周,包含7天)
- M(月,包含30天)
- y(年,包含365天)
4.在配置中使用变量
log_format main '$remote_addr - $remote_user [$time_local] "$request"'
# 如remote_addr是一个变量,使用时需要加上$符合。这种变量只有少数模块支持,并非通用。
Nginx服务的基本配置
Nginx运行时,至少必须加载几个核心模块和一个事件类模块。
这些模块运行时所支持的配置项称为基本配置——所有其他模块执行时都依赖的配置项。
基本配置项分为:
- 调试、定位问题配置项
- 正常运行的必备配置项
- 优化性能的配置项
- 事件类配置项(有些事件类配置项归到优化性能配置项)
1.用于调试进程和定位问题的配置项
序号 |
分类 |
语法 |
默认 |
说明 |
序号 |
分类 |
语法 |
默认 |
说明 |
1 |
是否以守护进程方式运行Nginx |
daemon on/off; |
daemon on; |
守护进程(daemon)是脱离终端并在后台运行的进程。脱离终端是为了避免执行过程中信息在终端上显示,同时也避免进程被终端输入中断。 |
2 |
是否以master/worker方式工作 |
master_process on/off; |
master_process on; |
提供该方式方便跟踪调试Nginx。如果不使用该方式,在worker异常时无法fork出worker子进程来处理请求。 |
3 |
error日志的设置 |
error_log /path/file level; |
error_log logs/error.log error; |
错误日志是定位Nginx问题的最佳工具。level是日志级别,取值:debug,info,notice,warn,error,crit,alert,emerg。从左至右依次增大 |
4 |
是否处理几个特殊的调试点 |
debug_points [stop/abort] |
/ |
用于帮助用户跟踪调试Nginx。设置stop时,Nginx执行到这些调试点时就会发出SIGSTOP信息用以调试;设置abort时,会产生一个coredump文件,可使用gdp来查看。通常不使用该配置项。 |
5 |
仅对指定客户端输出debug级别日志 |
debug_connection [IP/CIDR |
/ |
该配置实际属于事件类配置,因此需写到events块events{debug_connection 10.224.66.14; debug_connection 10.224.57.0/24;} |
6 |
限制coredump核心转储文件的大小 |
worker_rlimit_core size; |
/ |
在Linux系统中,当进程发生错误或收到信号终止,系统会将进程执行时的内存内容(核心镜像)写入一个文件(core文件),用作调试,这就是所谓的核心转储(core dumps)。当Nginx进程出现一些非法操作(如内存越界)导致进程直接被操作系统结束时,会生成核心转储core文件,可从core文件获取当时的堆栈、寄存器等信息,帮助定位问题。若不对文件大小进行限制可能达到几GB,这样随便几次coredumps就会把磁盘占满。 |
7 |
指定coredump文件生成目录 |
working_directory_ path; |
/ |
worker进程的工作目录,这个配置唯一用途就是coredump文件所放置的目录,协助定位问题。需确保worker进程有权限向working_directory指定的目录中写入文件。 |
如果日志设置debug级别或使用debug_connection,在configure时加入--with-debug
2.正常运行的配置项
序号 |
分类 |
语法 |
默认 |
说明 |
序号 |
分类 |
语法 |
默认 |
说明 |
1 |
定义环境变量 |
env VAR/VAR=VALUE; |
/ |
该配置项可以让用户之间设置操作系统上的环境变量。eg:env TESTPATH=/tmp/ |
2 |
嵌入其他配置文件 |
include /path/file |
/ |
该配置项可以将其他配置文件嵌入到当前nginx.conf文件中,它的参数可以是相对路径(相对于Nginx的配置目录,即nginx.conf所在目录),也可以是绝对路径。eg:includ mime.types; include vhost/星.conf;库看到参数值可以是一个明确文件,也可以是含有通配符“*”的文件名,同时一次嵌入多个配置文件 |
3 |
pid文件路径 |
pid path/file; |
pid logs/nginx.pid; |
保存master进程ID的pid文件存放路径。默认与configure执行时的参数“--pid-path”所指定的路径是相同的,可随时修改,确保Nginx有权限在相应目标中创建pid文件,该文件直接影响Nginx是否可以运行。 |
4 |
Nginx worker进程运行的用户及用户组 |
user username[groupname]; |
user nobody nobody; |
user用于设置master进程启动后,fork出的worker进程运行在哪个用户和用户组下。当按照“user username;”设置,用户组名与用户名相同。若用户在configure参数执行时使用--user=username和--group=groupname时,nginx.conf将使用参数中指定的用户和用户组。 |
5 |
指定Nginx worker进程可以打开的最大文件句柄描述符个数 |
worker_rlimit_nofile limit; |
/ |
设置一个worker进程可以打开的最大文件句柄数。 |
6 |
限制信号队列 |
worker_rlimit_sigpending limit; |
/ |
设置每个用户发往Nginx的信号队列的大小。即,当某个用户的信号队列满了,这个用户再发送信号量会被丢掉。 |
3.优化性能的配置项
序号 |
分类 |
语法 |
默认 |
说明 |
序号 |
分类 |
语法 |
默认 |
说明 |
1 |
Nginx worker进程个数 |
worker_processes number; |
worker_processes 1; |
master/worker运行方式下,定义worker进程个数。worker进程数量会直接影响性能,配置多少个worker进程与业务需求有关。每个worker都是单线程的进程。它们会调用各个模块以实现多种多样的功能。如果这些模块确认不会出现阻塞式调用,有多少CPU内核就应该配置多少个进程。反之,应配置稍多一些的worker进程。如:业务方面致使用户读取本地磁盘上的静态资源文件,而且服务器上的内存较小,以至于大部分的请求访问静态资源时都必须读取磁盘(磁头寻址是缓慢的),而不是内存中的磁盘缓存,那么磁盘I/O调用可能会阻塞worker进程少量时间,进而导致服务整体性能下降。多worker进程可以重发利用多核系统架构,但若worker进程数多于CPU内核数,会增大进程间切换带来的消耗(Linux是抢占式内核)一般情况下,用户应配置CPU核数相同的worker进程数,并绑定CPU内核 |
2 |
绑定Nginx worker进程到指定的CPU内核 |
worker_cpu_affinity cpumask [cpumask...] |
/ |
为什么要绑定?假设每一个worker进程都是非常繁忙,如果每一个worker都在抢同一个CPU,那么会出现同步问题。反之,每一个worker独享一个CPU,就在内核的调度上实现完全的并发。eg:有4颗CPU内核,就可以进行如下配置:worker_processes 4; worker_cpu_addinity 1000 0100 0010 0001;该配置仅对Linux操作系统有效,它使用sched_sctaffinity()系统调用实现这个功能。 |
3 |
SSL硬件加速 |
ssl_engine device; |
/ |
如果服务器上游SSL硬件加速设备,就可以进行配置加快SSL协议的处理。可以使用OpenSSL提供的命令查看是否有SSL硬件加速设备:openssl engine -t |
4 |
系统调用gettimeofday的执行频率 |
timer_resolution t; |
/ |
默认情况下,每次内核的事件调用(epoll、select、poll、kqueue等)返回时,都会执行一次gettimeofday,实现用内核的时钟更新一次Nginx中缓存时钟。中间有一次内核态到用户态的复制,因此,实现代价不小。可以使用该配置降低调用频率。eg:timer_resolution 100ms;表示至少每100ms才调用一次gettimeofday。但目前大多数内核中,x86-64体系架构,gettimeofday只是一次vsyscall,仅仅对共享内存页中的数据做访问,并不是通常的系统调用。一般不需使用该配置,若希望日志时间更准确可以使用。 |
5 |
Nginx worker进程优先级设置 |
worker_priority nice; |
worker priority 0; |
用于设置Nginx worker进程的nice优先级,在Linux或其他Unix操作系统中,当许多进程都处于可执行状态时,将按照所有的进程的优先级来决定本次内核选择哪一个执行。进程所分配的CPU时间片大小与进程优先级相关。成正比,即优先级越高,分配的时间片也越大。(默认最小时间片5ms,最大时间片800ms),优先级高的会占用更多的系统资源。优先级由静态优先级和内核根据进程执行情况所做的动态调整(目前只有+-5的调整)共同决定。nice值是进程的静态优先级,它的取值范围是-20~+19,从高至低。若希望Nginx占有更多资源,可以将nice值设置小一点但不建议小于内核进程nice值(通常为-5) |
4.事件类配置项
序号 |
分类 |
语法 |
默认 |
说明 |
序号 |
分类 |
语法 |
默认 |
说明 |
1 |
是否打开accept锁 |
accept_mutex[on/off]; |
accept_mutex on; |
accept_mutex是Nginx负载均衡锁。这把锁可以让多个worker进程轮流地、序列化地与新的客户端建立TCP连接。当某一个worker建立的连接数达到worker_connections配置的最大数7/8时会大大减小该worker试图建立TCP连接的机会。以此实现所有worker进程之上处理的客户端请求数尽量接近。该锁默认打开。若关闭,建立TCP耗时会更短,但worker进程之间的负载会非常不均衡,不建议关闭。 |
2 |
lock文件的路径 |
lock_file path/file; |
lock_file logs/nginx.lock |
accept锁可能需要这个lock文件,如果accept锁关闭,lock_file配置完全不生效。若打开锁,且由于编译程序、操作系统结构等因素导致Nginx不支持原子锁,这时才会用文件锁实现accept锁,lock_file指定的lock文件才会生效。 |
3 |
使用accept锁到真正建立连接之间的延迟时间 |
accept_mutex_delay Nms; |
accept_mutex_delay 500ms; |
使用accept锁,同一时间只有一个worker进程能够取到accept锁。该锁不是阻塞锁,若娶不到立刻返回,若一个worker视图取accept锁,取不到需要等accpet_mutex_delay定义的时间间隔后才能再次取锁。 |
4 |
批量建立新连接mult_accept [on/off]; |
multi_accept off; |
当事件模型通知有新连接时,尽可能对本地调度中客户端发起的所有TCP请求都建立连接。 |
|
5 |
选择事件模型 |
use [kqueue/rtsig/epoll/ /dev/poll /select/poll/eventport]; |
Nginx会自动使用最合适的事件模型 |
对于Linux操作系统,可供选择的事件驱动模型有poll、select和epoll三种。epoll当然是性能最高的。 |
6 |
每个worker的最大连接数 |
worker_connections number; |
/ |
每个worker进程可以同时处理的最大连接数。 |
用HTTP核心模块配置一个静态Web服务器
静态Web服务器的主要功能由ngx_http_core_module模块(HTTP框架的主要成员)实现。
http {
gzip on;
upstream {
...
}
...
server {
listen localhost:80;
...
location /webstatic {
if ... {
}
root /opt/webresource;
...
}
location ~*.(jpg|jpeg|png|jpe|gif)$ {
...
}
}
server {
...
}
}
所有HTTP配置项都必须直属于http块、server块、location块、upstream块或if块等(HTTP配置项自然必须会在http{}块之内)。
Nginx为配置一个完整的静态Web服务器提供了非常多的功能,分为以下8类:虚拟主机与请求的分类、文件路径的定义、内存及磁盘资源的分配、网络连接的设置、MIME类型的设置、对客户端请求的限制、文件操作的优化、对客户端请求的特殊处理。
1.虚拟主机与请求的分发
经常有多个主机域名对应着同一个IP地址情况,这时在nginx.conf中就可以按照server_name(对应用户请求的主机域名)并通过server块来定义虚拟主机,每个server块就是一个虚拟主机,它只处理与之对应的主机域名请求。
一台服务器上的Nginx以不同的方式处理访问不同主机域名的HTTP请求。
序号 |
分类 |
语法 |
默认 |
配置块 |
说明 |
序号 |
分类 |
语法 |
默认 |
配置块 |
说明 |
1 |
监听端口 |
listen address:port[default(在0.8.21已废弃)]/[default_server]/[bcaklog=num]/[rcvbuf=size]/[sndbuf=size]/[accept_filter=filter]/[deferred]/[bind]/ [ipv6only=[on/off]] /[ssl] |
listen 80; |
server |
listen参数决定Nginx服务如何监听端口。在listen后可以只加IP地址、端口号或主机名。不加端口号,默认监听80端口。参数说明:default/default_server--将所在的server块作为整个Web服务默认server块。如果没有设置该参数,将在nginx.conf配置文件中找到第一个server作为默认server块。如果无法匹配配置文件中的所有主机域名时,则会使用默认虚拟主机; backlog=num--表示TCP中backlog队列的大小。默认为-1,表不予设置。若设置队列满了,客户端建立连接将会失败; revbuf=size--表设置监听句柄的SO_RCVBUF参数; sndbuf=size--表设置监听句柄的SO_SNDBUF参数; accept_filter--设置accept过滤器,只对FreeBSD操作系统有用;deffered--在设置参数后,若用户发起连接请求,且完成了TCP的三次握手,内核也不会为这次的连接调度worker进程来处理,只有用户真的发生数据(内核已经在网卡中收到请求数据包),内核才会唤醒worker进程处理这个连接。【这个参数适用于大并发情况下,减轻worker进程的负担。】;bind--绑定当前端口/地址对,如127.0.0.1:8000,只有同时对一个端口监听多个地址时才会生效;ssl--在当前监听的端口上建立连接必须基于SSL协议。 |
2 |
主机名称 |
server_name name[...]; |
server_name ""; |
server |
server_name后可跟多个主机名称,如server_name wwww.testweb.com、download.testweb.com;在处理一个HTTP请求时,Nginx会取出header头中的Host与每个server中的server_name进行匹配,以此决定到底由哪一个server来处理这个请求。有可能一个Host与多个Server块中的server_name都匹配,这时会根据匹配优先级选择实际处理的server块。server_name与Host的匹配优先级:1)首先匹配选择所有字符串完全匹配的server_name,如www.testweb.com 2)其次选择通配符在前面的server_name,如.testweb.com 3)再次选择通配符在后面的server_name,如www.testweb. 4)最后选择使用正则表达式才匹配的server_name,如~^.testweb.com$;若都不匹配,会按下列顺序选择处理server块:1)优先选择listen配置项后加入[default |
3 |
server_names_hash_bucket_size |
server_names_hash_bucket_size size; |
server_names_hash_bucket_size 32 |
64 |
128; |
4 |
server_names_hash_max_size |
server_names_hash_max_size size; |
server_names_hash_max_size 512; |
http、server、location |
该配置项会影响散列表的冲突率,值越大消耗的内存越多,但散列key的冲突率越低,检索速度更快;值越小,消耗内存越小,但散列key的冲突率可能增高 |
5 |
重定向主机名称的处理 |
server_name_in_redirect on/off; |
server_name_in_redirect on; |
http、server或location |
该配置需配合server_name使用,on打开时,表示重定向请求时会使用server_name里配置的第一个主机名代替原先请求的Host头部;使用off时,则重定向请求时使用请求本身的Host头部 |
6 |
location |
location[=//*/^~/@]/uri/{...} |
/ |
server |
该配置会根据用户请求中的url来匹配上面的/uri表达式,如果可以配置则选择location{}块中的配置来处理用户请求。location匹配规则:1)=表示把uri作为字符串,完全匹配 2)~表示uri是大小写敏感的 3)~*表示忽略字母大小写问题 4)^~表示匹配uri只需前半部分与uri匹配即可,如location ~^ /image/{# 以/image/开始的请求都会匹配上} 5)@表示仅用于Nginx服务内部请求之间的重定向,带有@的location不直接处理用户请求。location是有顺序的,当一个请求匹配多个时,实际这个请求是被第一个处理 |
Nginx正是使用server_name配置项针对特定Host域名的请求提供不同的服务,以此实现虚拟主机功能。