Nginx(三)配置文件

文章目录

  • Nginx
    •  Nginx的基本配置项
      •   用于调试的配置项
      •   运行所需的配置项
      •   优化性能配置项
    •  http核心模块的配置项
      •   MIME类型的配置
      •   文件操作的配置
      •   网络连接的配置
      •   虚拟主机的配置
      •   路径的配置项
    •  多个配置项冲突的处理
  • 结束语

Nginx

  在第一章的时候先稍微提及了一下Nginx的配置文件中的基本语法格式。接下来就对配置文件进一步的解析。

 Nginx的基本配置项

   所谓的Nginx的基本配置项,就是核心类模块以及事件类模块所需以及所支持的配置项,实际上就是一个全局配置项。接下来分别从以下三个角度来介绍:

  • 用于调试的配置项
  • 运行所需的配置项
  • 优化性能的配置项

  用于调试的配置项

   何为调试,其实就是在服务上线之前,我们需要去确保所提供的服务能够正常运行,反过来而言,就是通过相应的配置项来达到定位问题。
   在第二章的时候曾说过,实际使用的时候,我们都是让Nginx以多进程的方式来提供服务的。而Nginx其实是有单进程模式的,由以下配置项来控制:

master_process on | off

   默认情况下,该配置项的值是on,也就是说,Nginx默认是以多进程模式来提供服务的。我们将其修改为off,启动Nginx,查看其进程相关信息,如下所示:

   从结果来看,可以知道将该配置项的值更改为off以后,父进程master就不会fork出worker子进程来处理请求,而是用master进程来处理请求。

   既然调试是为了防止出现错误,那么当错误产生时,我们应该怎么去定位错误。换句话而言,我们应该将错误记录到一个文件当中,然后告诉Nginx这个文件的位置。那么为了让Nginx能够将产生的错误信息记录到相关文件中,其提供了以下配置项:

error_log /path/file level;

   我们在nginx.conf这个配置文件中可以看到该配置项的相关默认配置,如图所示:

   参数中的/path/file指定一个具体的文件,比如说图中的logs/error.log,但实际上最好是将该文件放置到一个足够大的磁盘中。因为第二个参数level决定了记录的信息量,也就是所谓的日志输出级别。其取值范围如下所示:

debug、info、notice、warn、error、crit、alert、emerg(从左到右依次增大)

   当我们设为level为error时,包括error以及比error大的级别的日志都会被输出到日志文件中。那么如果假设我们将level设为debug级别,就会输出所有级别的日志,最直观的体现就是文件大小的剧增,因此我们需要有足够大的磁盘去存放该日志文件。

   在这里需要注意的是:如果需要输出debug日志文件,必须在configure编译的时候加上–with-debug配置项

   那么这时候思考一个问题,为了能够准确定位问题,我们是否能够针对性的输出debug日志,即针对某一个或者某一类请求输出debug级别的日志。实际上,在Nginx中是有提供这样的相关配置项的,但这个配置项需要放在events配置块下才能生效,其语法如下所示:

debug_connection [IP | CIDR]

   只要配置了这个debug_connection,就能将指定IP地址的请求输出为debug日志,而至于其他没有指定的请求则以error_log为准。

   除了查看日志信息以外,我们还可以通过查看堆栈以及寄存器等信息来定位问题。比如在Linux中就有一个所谓的核心转储(coredumps)来提供这样的便利性,我们可以通过gdb查看coredumps来定位问题。但实际上这种coredumps文件,会记录很多信息,大多数可能并不是我们需要的,因此我们需要对其进行限制。在Nginx中提供了以下配置项:

working_directory path;
worker_rlimit_core size;

   第一个配置项指定了coredumps文件所放置的目录,第二个则是设置coredumps文件的大小。通过适宜的设置,我们就可以方便快速定位问题。

  运行所需的配置项

   一般来说,我们不会在nginx.conf里放置太多相关配置,为了方便管理以及维护,会将许多配置分为相对应的文件。比如我们要导入一个rewrite模块的配置示例,我们就会在conf目录下新建一个rewrite.conf,然后通过include配置项将其添加到nginx.conf中,语法格式如下:

include /path/file;

   需要知道的是,include配置项的参数可以是绝对路径,也可以是相对路径(其相对于nginx.conf的目录)。

   那么当我们打开nginx.conf的时候,第一个看到的是顶部的一个配置项:

#user nobody;

   从配置项的名称user来看,不难得知是nginx进程的所属用户,换句话而言就是nginx能够拥有的权限。实际上,这个配置项用于设置worker进程运行在哪个用户以及用户组下,默认情况是nobody。

   那么这样的配置项到底有什么作用呢?这是因为对于系统中的文件,用户有没有权限访问或执行,而在这里用户就等同于是nginx该程序。

   那么nobody又是什么呢?这其实是linux中的系统用户,但是这个用户是不能够登录的。Linux系统为了安全性,很多服务的运行甚至是操作都不是运行在root用户下的,而是运行在这个nobody用户下。这里需要根据具体情况来具体配置。

  优化性能配置项

   在前面提到nginx的进程模型的时候,曾经讲过一个worker_processes,即worker进程的数量。在前面的时候讲配置的数量最好是与CPU内核数相关,实际上,如果进程调用的模块内存在阻塞式调用时,我们就需要配置更多的worker进程,但不能过多。如果设置过多则会增加进程间切换的消耗。

   而一般情况下,除了设置相应的worker进程数量以外,我们还需要将worker进程绑定到指定的CPU内核,而Nginx就提供了这样一个配置项:

worker_cpu_affinity cpumask[cpumask]

   通过官网得知,其用法如下所示:

worker_processes 4;
worker_cpu_affinity 0001 0010 0100 1000;

   在这里配置了四个worker进程,对应四核CPU。有多少核数,就用多少位数表示,那么0001则是使用CPU0,0010则是使用CPU1,其余以此类推。

   那么为什么要绑定worker进程到指定的CPU内核呢? 这是因为,如果出现多个worker进程都被调度到同一个CPU,就会产生竞争现象。那么如果每个worker进程都调度到不同的CPU,就会减少上下文切换,提高效率。

   那么既然提到了CPU上下文切换,就得说说进程优先级。当许多进程处于可执行状态时,操作系统将会按照这些进程的优先级来决定内核选择哪一个进程拿到时间片执行。优先级越高,进程分配到的时间片也就越大。而在Nginx中也提供了worker进程优先级设置的配置项,如下所示:

worker_priority nice;

   该配置项的参数nice代表了进程的优先级,其取值范围从-20~+19m。其中,-20是最高优先级,+19是最低优先级。如果想要进程被分配的时间片更多,也就是Nginx占有更多的系统资源,那么就将优先级提高,也就是将值降低,但尽量不低于-5(内核进程的优先级)。

  在了解完Nginx的基本配置项以后,接下来就来看http核心模块的相关配置项介绍。

 http核心模块的配置项

  MIME类型的配置

   打开配置文件,找到http配置项块,首先看到前两行,如图所示:

   第一行include配置项导入的是MIME-TYPE,定义MIME类型到文件扩展名的映射,也就是说告诉Nginx可识别的文件类型。而第二行的default_type则是当找不到相应的映射的时候,就会使用这个默认的MIME-TYPE。

   通过查询官方文档,除此之外,还有其他的MIME类型相关的配置项,如下所示:

types_hash_bucket_size size;
types_hash_max_size size;

   为了能够快速定位到相应的MIME-TYPE,Nginx使用了哈希表来存储MIME-TYPE以及其相对应的文件扩展名。第一个配置项设置了每个hash桶占用的内存大小,而第二个配置项则是设置了整个哈希表的大小。

   需要知道的是:这个max_size越大,就会使哈希表的冲突率降低,加快检索速度,反之,越小则增高冲突率,降低检索速度。

  文件操作的配置

   接下来我们再来看这个图:

   首先需要知道的是,sendfile是Linux的一个系统调用,它的直接体现是从磁盘读取文件后直接在内核态就发送到网卡设备上,也就是说,它减少了内核缓冲区和用户缓冲区之间的内存复制(所谓的零拷贝),提高了发送文件的效率。

   那么从配置上来看就可以知道,这个配置项的参数的值on|off代表了是否启用Linux系统的系统调用sendfile。

   而对于第二个配置项tcp_nopush则是表示,当我们开启了sendfile配置时,如果与此同时我们也打开了tcp_nopush则将会在发送响应时,将整个response header放到一个TCP包内发送。

   那么和sendfile功能类似的还有两个:aio以及directio,在这里不过多阐述。

   在前面的时候说过Nginx可以配置静态资源服务器,那么为了提高静态资源的访问效率,Nginx会将最近访问的文件的文件描述符以及元数据存储在缓存中。而如果想要使用这个缓存,Nginx有相应的配置项open_file_cache,其语法格式如下所示:

open_file_cache off;
open_file_cache max=N [inactive=time];

   这个配置项默认是关闭的,当我们想要使用的时候就得使用第二个语法格式。那么max到底是什么呢?max是表示在内存中存储元素的最大个数,而如果超过了这个设定的最大个数,Nginx就会采用LRU算法去淘汰冷数据(即最近最少使用的元素)。而inactive是指非活动时间,也就是说,在这个规定的时间内,没有被访问过的元素将会被淘汰掉。默认是60秒,如果没有必要,无需改这个默认值。

   这里有一个配置项是配合inactive参数使用的,如下所示:

open_file_cache_min_uses number;

   这个配置项是指在非活动时间段内,访问次数超过了指定的最小次数number,就不会被淘汰。

   那么除了缓存上述的文件描述符以及相关元数据以外,还可以缓存访问文件时发生的错误,比如权限被拒绝或者路径没找到等,而默认情况下是开启这样的缓存的,如果想要开启这个缓存,需要用以下配置项:

open_file_cache_errors on|off;

   除了非活动时间段的设置以外,还有一个时间设置是用于校验缓存中的文件元信息是否是最新的,如下所示:

open_file_cache_valid time;

   其默认值为60s,也就是说,如果在这个时间段内,文件元信息并不是最新的,它就会更新文件的元信息。

   那么了解了上述的配置项以后,如果静态文件内容变化频率较高,就会把open_file_cache_valid的值设置的小一些,反之,则设置大一些。

  网络连接的配置

   看完了文件操作的配置以后,我们再来看下面的这张图:

   从配置项的名称可以看到这是和HTTP请求中的keepalive功能相关,它的作用是让多个请求复用一个TCP连接,也就是说它保证了端到端的连接持续有效。

keepalive_disable[msie6|safari|none]

   首先来看第一个配置项,这个配置项是对指定的浏览器禁用keepalive功能,默认是ie6以及safari。从官网的文档说明来看,可能因为这两个浏览器对使用了keepalive功能的POST请求的处理具有一定的问题。

   那么既然说到了连接复用,我们就得想到,一个连接上到底能够承载多少个请求?我们是否可以去指定它?实际上,Nginx提供了这样的一个配置项,如下所示:

keepalive_requests number;

   默认情况是一个keepalive连接最多可以承载100个请求。当达到请求最大值时,连接就会关闭。

   最后就是最重要的超时设置,配置项如下所示:

keepalive_timeout timeout [header_timeout];

   这个配置项的意思是,在timeout时间(默认75秒)内,仍然保持活动的连接处于打开状态。而如果当连接处于非活动状态超过一定的时间timeout后,这个连接就会被关闭。而第二个参数header_timeout则是指设置响应头中的一个“Keep-Alive:timeout = time”的属性,这个属性火狐浏览器是可以识别的。

   但是需要知道的是,这个配置项只是在Nginx服务器上的,也就是说这只是告诉Nginx服务器何时关闭自己端的空闲连接。当然,Nginx也会将这个时间传回给浏览器,让浏览器做进一步处理,但处理的方式可能是不一样的。

   和keepalive_timeout配置项相类似的timeout类型配置项还有以下几个:

client_header_timeout time;
client_body_timeout time;
send_timeout time;

   我们先来看第一个配置项client_header_timeout,它的默认值是60s。这个配置项的意思是:如果在一个时间段内服务器没有读取到客户端发来的整个HTTP头,那么就认为连接超时并且返回给客户端一个408响应码。

   第二个配置项client_body_timeout和第一个配置项相似,默认值同样是60s,一样会返回408响应码。但是这个timeout代表的不是读取整个body的时间而是两次连续的读操作之间的一段时间。

   至于第三个配置项send_timeout则是配置发送响应的超时时间,如果当Nginx服务器向客户端发送了响应,但是客户端在这段时间内没有接收这个响应,那么Nginx就会关闭这个连接。

   在超时这一块多次提到了关闭连接这个操作,而在配置项中是存在控制Nginx关闭连接方式的相关配置的,如下所示:

lingering_close off | on | always;
lingering_time time;
lingering_timeout time;

   首先我们来看第一个配置项lingering_close,它的参数控制Nginx如何关闭客户端连接。比如默认值on,表示nginx在关闭连接前会处理完来自客户端的有必要处理的数据。而off则是表示nginx无需等待直接关闭连接,一般情况都不要用这个参数。那么对于always呢,则是表示Nginx关闭连接前得处理完当前连接上所有客户端发送的数据。

   第二个配置项lingering_time则表示Nginx处理其他客户端的数据的最长时间,也就是说,如果超过了设定的这个时间,即使后面还有其他数据,这个连接都会被关闭。

   而最后一个配置项lingering_timeout则表示Nginx等待更多数据的最长时间。Nginx在关闭连接前,会检查是否还有客户端发送数据到服务器,如果在lingering_timeout这个时间段内没有接收到数据,它就会将连接关闭;否则,它就会读取完连接缓冲区上的数据,然后继续等待新的数据。在这样的反复过程中,如果超过了lingering_time则直接关闭连接。

  虚拟主机的配置

   在配置文件中,可以看到占比比较大的一个配置块项server。每一个server块都是一个虚拟主机,负责处理与之相对应的主机域名请求。也就是说,我们可以达到一个这样的效果:在一台服务器上以不同方式处理不同主机域名的请求。那么,接下来我们来看看它的相关配置项。

   首先来看第一个配置项listen,其语法格式如下所示:

listen address[:port]
listen port
listen unix:path

   这个配置项的参数决定了Nginx如何去监听端口,比如说,通过IP地址(IPv4、IPv6)、端口或者主机名,如下所示:

listen 127.0.0.1:8000; #监听指定IP:端口
listen 127.0.0.1; #不加端口,默认监听80端口
listen 8000;
listen *:8000; #通配符监听端口->等同于上面监听8000
listen localhost:8000; #监听主机名
listen [::]:8000; #IPv6

   实际上,listen配置项还可以添加其他参数,这里列举一部分参数,如下所示:

参数 含义
default_server 所在server块为服务器默认server块
ssl 当前监听的端口中上建立的连接需要基于SSL协议
http2 当前监听的端口上可以接收HTTP2协议的连接
backlog=num 设置TCP中backlog队列的大小,默认为-1
accept_filter 设置accept过滤器
deferred 调用延时的accept方法

   这里挑default_server以及deferred稍微讲解一下,首先是default_server,为什么需要设置默认server块呢?其实是因为当一个请求无法匹配到配置文件中任何一个主机域名时,Nginx就会使用默认的server块。

   那么deferred又是什么呢?我们知道HTTP协议是TCP协议的上层,那么在客户端准备和服务器建立连接之前,会先完成TCP的三次握手。那么当完成了TCP的三次握手以后,Linux系统内核也不会立刻调度worker进程去处理当前这个连接,而是等到内核在网卡中收到了数据包,才会调度worker进程去处理这个连接,这样的处理就减少了在高并发场景下的worker进程的压力。

   接下来我们再来看第二个配置项server_name,这个配置项的语法如下所示:

server_name name …;

   省略号就代表了这个配置项后可以跟多个域名,而域名的格式可以是一个明确的域名、带通配符的泛域名,甚至可以是一个正则表达式,也就是如下格式:

   在开始处理HTTP请求之前,我们需要确定这个请求所匹配的配置,也就是说,server_name就是Nginx用来针对指定域名的请求提供不同的服务的一个配置项。

   需要知道的是,在开始处理请求之前,Nginx会取出header中的Host与每一个server块的server_name进行匹配。但是有可能Host会对应多个server块下的server_name,那么我们就需要一个匹配优先级来决定到底实际匹配上的server块。接下来我们就来了解一下server_name和Host之间的一个匹配顺序。

   1.首先Nginx会优先匹配明确的域名。这是什么意思呢?就是Nginx会优先匹配到不带通配符、不带正则表达式的明确的字符串域名。
   2.如果第一步并没有匹配到明确的域名,那么就会先匹配*在前的泛域名(即*.example.com)。
   3.如果*在前的泛域名没有匹配到,那么就会再匹配*在后的泛域名
   4.最后才会使用正则表达式匹配
   5.那么如果前面四种都没有匹配到相应的server块,就会匹配listen配置项后跟了default_server的server块或者匹配listen端口的第一个server块。

   需要知道的是,前面三种的匹配顺序和nginx.conf即配置文件中server块出现的顺序无关。但是唯独正则表达式取匹配上的server块和配置文件中的顺序有关。也就是说,如果根据正则表达式同时有两个server块匹配上了,会匹配两者在配置文件中最前的那一个。

   在这里以一个示例来演示server的匹配顺序,在这之前,我们先通过ifconfig命令配置一个新的ip,如图所示:

Nginx(三)配置文件_第1张图片

   配置完新的ip以后,这里为了简便演示,索性修改了服务端的hosts文件,如下所示:

   接下来就可以正式地开始配置我们的虚拟主机,创建一个server_name_example.conf文件,其内容如下所示:

Nginx(三)配置文件_第2张图片

   这里我们依次注释相关的server块以及curl命令访问每一次这个域名,相应的结果如下所示:

Nginx(三)配置文件_第3张图片

   通过以上的示例我们可以知道server块的匹配顺序。值得注意的是,当我们用正则表达式的时候,可以用小括号来创建变量,除了上图中的方式以外,也可以给变量赋名,如下所示:

   在server_name中,我们将在server_name后跟的多个域名中的第一个域名称为主域名。那么这个主域名我们到底有什么作用呢?实际上这里需要一个server_name_in_redirect配置项,其默认值为off。当它为on时,它就会在重定向时会使用第一个域名即主域名代替原先请求中的Host。接下来以如下配置为例:

   然后我们再用curl命令来访问www.scorpion.com,结果如图所示:

Nginx(三)配置文件_第4张图片

   接下来我们来讲下一个配置项location,先来看一下它的语法格式:

location [ = | ~ | ~* | ^~ ] uri { … }
location @name { … }

   location它作用是根据用户请求中的URI来匹配参数中的uri表达式,如果匹配成功,就以匹配到的location块中的配置来处理用户请求。接下来我们就来了解它的匹配规则。

   首先是第一个匹配规则前缀uri,也就是一个字符串,只要URI中存在参数中的uri,就可以执行这个location块下的配置,如下所示:

location /abc {}
以下地址可匹配:
example.com/abc、example.com/abc/、example.com/abcd等

   再来看第二个匹配规则=,它表示精确匹配,也就是说,只有当URI与参数中的uri完全匹配的时候,才会执行这个location块下的配置,如下所示:

location = /example {} #只有当用户请求的uri是/example时才会使用该location下的配置

   而第三个匹配规则~,它表示大小写敏感匹配,也就是说,只有当URI与参数中的uri字母大小写一致,才会执行这个location块下的配置,如下所示:

location ~ ^/Abc$ {}
以下地址可匹配:example.com/Abc

   和第三个匹配规则相反的是~*,它是表示忽略大小写匹配,也就是说,只要URI与参数中的uri的字母一样,就可以执行这个location块下的配置,如下所示:

location ~* ^/ABc$ {}
以下地址可匹配:
example.com/abc、example.com/Abc、example.com/ABC等

   接下来再来看第四个匹配规则^~,它和前缀匹配是一样的,但是如果匹配到它就不会再去找其他匹配,并且它是大小写敏感的匹配,如下所示:

location ^~ /aBc {}
以下地址可匹配:
example.com/aBc、example.com/aBc/

   最后我们再来看这个@,它表示仅用于Nginx内部请求之间的重定向,也就是说,它不会去处理用户请求。

   了解了匹配规则以后,那么我们同样需要了解location的匹配顺序问题,以下就是它的匹配顺序规则:

    1.在Nginx中存在一个二叉树,用于存放所有的前缀字符串,它会先遍历那些匹配到的前缀字符串的location;
    2.然后如果在参数中有=,那么就与=相当于的location匹配上并且停止接下来的匹配,使用这个location块下的配置处理请求;
    3.如果没有=符号而是^~符号时就使用这个匹配上的location块下的配置处理请求,它同样也是停止接下来的匹配;
    4.那么如果前面两种都没有遇到,那么它就会开始按照Nginx.conf中location出现的顺序依次做正则表达式的匹配;
    5.如果连正则表达式都没有匹配上了,那就再使用匹配上的最长的前缀字符串的location去处理请求。

   接下来我们以一个示例来演示其规则,首先我们来看一下相关的配置,如下所示:

Nginx(三)配置文件_第5张图片

   对于前缀匹配,是只要URI中存在参数中的uri,即可执行这个location块下的配置,在这里对其不进行演示。

   那么如果uri是/abc它能匹配到的是/abc的前缀匹配以及=/abc的精确匹配。根据匹配规则,应该是精确匹配,这里尝试用curl命令去访问/abc,结果如下所示:

   再者如果是/abc/呢?实际上会匹配到/abc的前缀匹配以及^~/abc/的匹配,这里我们对比匹配,依次将相应的location块注释,再依次访问,结果如下所示:

Nginx(三)配置文件_第6张图片

   而对于访问的是/ABc/呢,那么只会访问到~/ABc/的location块,这里我们对比匹配,如下所示:

Nginx(三)配置文件_第7张图片

   这里我们再来访问/abc/def,它能匹配到的是/abc/def的前缀匹配以及忽略大小写的*匹配。根据匹配规则,应该是匹配大小写忽略的*匹配,结果如下所示:

   那么其实/abc/def/的结果就是匹配到/abc/def的前缀匹配,理应返回longest prefix string match。因为我们的正则表达式中是用了$结尾。

  路径的配置项

   既然讲了location,那么就讲讲和location下几个相关的配置项。

   在前面的时候讲过配置静态资源服务器,其中提到了root和alias。这两个配置项都是用于设置资源路径,那么实际上root可以出现的Context上下文比alias可以出现的Context上下文多,alias只能出现在location块中,而root配置项除了可以出现在location以外,还可以出现在http、server甚至是if块中。

   而root和alias的区别也非常容易理解,比如说我们有一个请求URI是/images/cat.jpg,而实际的磁盘位置是/usr/local/nginx/images/cat.jpg。那么对于root和alias的设置方式,即如下所示:

location /images {
    root /usr/local/nginx;
}

location /images {
    alias /usr/local/nginx/images;
}

   使用root时,它会将root后跟的path参数添加到URI前。而alias则是将URI替换成path参数的值。

   location配置项下还可以配置网站的首页,而这通过index配置项来完成,其语法格式如下所示:

index file …;

   从语法后可以跟多个文件参数,Nginx会按照参数的顺序来访问指定的文件。

   我们在配置文件中还看到了error_page配置项,其语法格式如下所示:

error_page code … [=[response]] uri;

   error_page这个配置项中的参数code是错误码,而参数中的uri则是重定向的页面uri,那么从这一番介绍就可以知道,它是根据HTTP返回码来重定向页面。例如:

error_page 404 /404.html

   但是这里需要主要的是,它只是重定向了URI,并没有更改错误码。也就是说,它原先返回码是什么,重定向后还是与原来的相同。如果我们想更改返回码,可以通过“=”来更改返回码,比如以下格式:

error_page 404 =200 /empty.html

   当然其实也不一定是uri,也可以重定向到location,比如说以下情况:

location /test {
   error_page 404 @redirect
}
location @redirect {
   proxy_pass uri; #反向代理
}

   那么在配置静态资源服务器的时候还可以使用一个配置项try_files,它的语法如下所示:

try_files file … uri;
try_files file … =code

   对于try_files,它的作用就像它的名字一样,尝试寻找文件。这是什么意思呢?比如说,现在try_files后跟了path1、path2等等,那么它就会按照顺序去访问每一个path所代表的文件,如果该文件可以被有效地访问,那么就直接向用户返回这个文件并结束请求,否则就继续按照顺序访问下一个文件。

   那么如果所有的path的文件都不是有效的,那么就会重定向到最后的参数uri,而且必须是有效性的重定向。除此之外,还可以在后面跟上返回的错误码,那根据上面的error_page,我们也可以搭配一起使用。

 多个配置项冲突的处理

   在上面了解配置项以及查看官方文档的过程中,不难发现,很多配置项它可以出现在很多的Context上下文中,比如说root,它既可以出现在http中也可以出现在server或location中,甚至是if配置块中。基于这样的一种情况,当一个配置项同时出现在多个配置块的时候,就有可能产生值冲突的情况。那么,到底发生值冲突的时候,以哪一个配置项的值为准?

   实际上,在多个配置项同时存在的时候,它是可以覆盖的,但只限于一类配置项,而另一类配置项是不能覆盖的。这是什么意思呢?比如说root配置项只是存储配置项的值,但没有指示或产生任何的行为,这一类配置项就是可以覆盖的。而另一类呢,比如说rewrite或者return配置项,Nginx解析到这样的配置项的时候,它就会产生一种行为。
至于怎么区分这两类配置项,一般来说,可以通过查看官方文档或者源码判断出来。

   那么源码中到底是如何体现的呢?其实我们只需要关注这个配置项是在哪些地方可以配置的。比如说我们找到Nginx目录下的src/http/modules,这里以index模块为例,其源码如下所示:

Nginx(三)配置文件_第8张图片

   在每个http模块都会有一个结构体ngx_module_t,在这个结构体里面定义了多个回调方法。而在每个模块中有一个ngx_command_t这样一个数组,用来存放该模块提供的配置项以及该配置项相关的信息。

   我们先来看下ngx_command_t结构体中的黄色字体部分,它就定义了index配置项能够出现的Context,可以看到他能够出现在http、server以及location下,并且它后面所跟的参数可以是多个。

   再来看ngx_http_module_t中的后面的方法,它有一个merge_loc_conf,也就是说将http、server块下的index合并到location块,换句话来说就是location块下的index配置项覆盖父配置块的index配置项。

   那么到底是怎么覆盖的呢,其实就是子配置不存在时,直接使用父配置,相当于就近原则。比如:

server {
   listen 8080;
   root /nginx/html;
   location /abc {
     root /html;
   }
   location /loc {
     …
   }
}

   上面的例子中,当我们访问/abc时,会使用匹配的当前location块中的root配置项。而如果我们再来访问/loc时,会使用server块下的root配置项,因为匹配上的当前location块下没有root配置项。

   通过了解这样的一个规则,我们就能够在可能没有配置的情况下却产生了意想不到的效果的场景下,找到相关的问题所在。

结束语

	'''
		在这一章呢,主要还是讲了一些关于HTTP的相关配置
		而反向代理以及负载均衡的相关配置不打算在这里讲
		对于这些配置项,主要有一个了解以及掌握即可
	'''

你可能感兴趣的:(Nginx,nginx)