Nignx架构详解、配置文件解释及模块相关语法

1、引言

Nginx拥有大量官方发布的模块和第三方模块,这些已有的模块可以帮助我们实现Web服务器上很多的功能。使用这些模块时,仅仅需要增加、修改一些配置项即可。 因此,本章的目的是熟悉Nginx的配置文件, 包括配置文件的语法格式、 运行所有Nginx服务必须具备的基础配置以及使用HTTP核心模块配置静态Web服务器的方法,最后还会介绍反向代理服务器。

2、Nginx进程模型

详细解释Nginx进程模型,优点,以及为什么这样做,后期将通过代码的方式去观察到低是如何实现的这些高效?
1、简单介绍模型
在正式提供服务的产品环境下,部署Nginx时都是使用一个master进程来管理多个worker进程,一般情况下, worker进程的数量与服务器上的CPU核心数相等。 每一个worker进程都是繁忙的, 它们在真正地提供互联网服务, master进程则很“清闲”, 只负责监控管理worker进程。 worker进程之间通过共享内存、 原子操作等一些进程间通信机制来实现负载均衡等功能。

nginx采用多进程的方式运行。nginx在启动后,会有一个master进程和多个worker进程。master进程主要用来管理worker进程,包含:接收来自外界的信号;向各worker进程发送信号;监控worker进程的运行状态;当worker进程退出后(异常情况下产生coredump),会自动重新启动新的worker进程。所以worker进程的权限要小于或等于master进程,这样master进程才可以完全地管理worker进程。而基本的网络事件,则是放在worker进程中来处理了。多个worker进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。worker进程的个数是可以设置的,一般我们会设置与机器cpu核数一致,这里面的原因与nginx的进程模型以及事件处理模型是分不开的。

Nginx是支持单进程(master进程)提供服务(这就和低版本的Libevent一样)了, 那么为什么产品环境下要按照masterworker方式配置同时启动多个进程呢? 原因有下面两点:

  • 由于master进程不会对用户请求提供服务,只用于管理真正提供服务的worker进程,所以master进程可以是唯一的,它仅专注于自己的纯管理工作,为管理员提供命令行服务,包括诸如启动服务、 停止服务、 重载配置文件、平滑升级程序等。
  • 多个worker进程处理互联网请求不但可以提高服务的健壮性(一个worker进程出错
    后, 其他worker进程仍然可以正常提供服务),最重要的是,这样可以充分利用现在常见的SMP多核架构, 从而实现微观上真正的多核并发处理。因此用一个进程(master进程)来处理互联网请求肯定是不合适的。一个worker进程可以同时处理的请求数只受限于内存大小(通过epoll监听), 而且在架构设计上,不同的worker进程之间处理并发请求时几乎没有同步锁的限制, worker进程通常不会进入睡眠状态(非阻塞socket,仅仅可能陷入epoll等待而已),因此,当Nginx上的进程数与CPU核心数相等时(最好每一个worker进程都绑定特定的CPU核心),进程间切换的代价是最小。

这里写图片描述
一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。每个worker进程里面,可以处理多个连接,worker进程竞争地accept后,将连接的accept_fd加入其epoll里面。然后当epoll返回可读可写的fd时候,循环处理多个准备好的事件即可,这样并没有带来任何额外的上下文切换,事件处理非常的轻量级,只是占用了一些内存空间即可。所以在Nginx配置的时候, 工作进程个数一般设定为cpu的核数,在这里就很容易理解了,更多的worker数,只会导致进程来竞争cpu资源了,从而带来不必要的上下文切换。这点和Libevent思路基本相似,通过epoll实现单进程处理高并发请求。

2、worker进程处理请求
worker进程又是如何处理请求的呢?我们前面有提到,worker进程之间是平等的,每个进程,处理请求的机会也是一样的。当我们提供80端口的http服务时,一个连接请求过来,每个进程都有可能处理这个连接,怎么做到的呢?首先,每个worker进程都是从master进程fork过来,在master进程里面,先建立好需要listen的socket(listenfd)之后,然后再fork出多个worker进程。所有worker进程的listenfd会在新连接到来时变得可读,为保证只有一个进程处理该连接,所有worker进程在注册listenfd读事件前抢accept_mutex,抢到互斥锁的那个进程注册listenfd读事件,在读事件里调用accept接受该连接。当一个worker进程在accept这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接,这样一个完整的请求就是这样的了。我们可以看到,一个请求,完全由worker进程来处理,而且只在一个worker进程中处理。

3、每个worker为何可以处理高并发
总体思路就是连接请求到来,多个work进程竞争抢占accept并将fd加入epoll,一个work通过epoll管理多个连接。几乎不涉及上下文切换带来的开销,全部都靠epoll实现。

nginx采用多worker的方式来处理请求,每个worker里面只有一个主线程,那能够处理的并发数很有限啊,多少个worker就能处理多少个并发,何来高并发呢?nginx可以采用异步非阻塞的方式来解决高并发问题。

nginx采用了异步非阻塞的方式(IO复用机制)来处理请求,也就是说,nginx是可以同时处理成千上万个请求的。想想apache的常用工作方式(apache也有异步非阻塞版本,但因其与自带某些模块冲突,所以不常用),每个请求会独占一个工作线程,当并发数上到几千时,就同时有几千的线程在处理请求了。这对操作系统来说,是个不小的挑战,线程带来的内存占用非常大,线程的上下文切换带来的cpu开销很大,自然性能就上不去了,而这些开销完全是没有意义的。

为什么nginx可以采用异步非阻塞的方式来处理呢,或者异步非阻塞到底是怎么回事呢?我们先回到原点,看看一个请求的完整过程。首先,请求过来,要建立连接,然后再接收数据,接收数据后,再发送数据。具体到系统底层,就是读写事件,而当读写事件没有准备好时,必然不可操作,如果不用非阻塞的方式来调用,那就得阻塞调用了,事件没有准备好,那就只能等了,等事件准备好了,你再继续吧。阻塞调用会进入内核等待,cpu就会让出去给别人用了,对单线程的worker来说,显然不合适,当网络事件越多时,大家都在等待呢,cpu空闲下来没人用,cpu利用率自然上不去了,更别谈高并发了。好吧,你说加进程数,这跟apache的线程模型有什么区别,注意,别增加无谓的上下文切换。所以,在nginx里面,最忌讳阻塞的系统调用了。不要阻塞,那就非阻塞喽。非阻塞就是,事件没有准备好,马上返回EAGAIN,告诉你,事件还没准备好呢,你慌什么,过会再来吧。好吧,你过一会,再来检查一下事件,直到事件准备好了为止,在这期间,你就可以先去做其它事情,然后再来看看事件好了没。虽然不阻塞了,但你得不时地过来检查一下事件的状态,你可以做更多的事情了,但带来的开销也是不小的。所以,才会有了异步非阻塞的事件处理机制,具体到系统调用就是像select/poll/epoll/kqueue这样的系统调用。它们提供了一种机制,让你可以同时监控多个事件,调用他们是阻塞的,但可以设置超时时间,在超时时间之内,如果有事件准备好了,就返回。这种机制正好解决了我们上面的两个问题,拿epoll为例(在后面的例子中,我们多以epoll为例子,以代表这一类函数),当事件没准备好时,放到epoll里面,事件准备好了,我们就去读写,当读写返回EAGAIN时,我们将它再次加入到epoll里面。这样,只要有事件准备好了,我们就去处理它,只有当所有事件都没准备好时,才在epoll里面等着。这样,我们就可以并发处理大量的并发了,当然,这里的并发请求,是指未处理完的请求,线程只有一个,所以同时能处理的请求当然只有一个了,只是在请求间进行不断地切换而已,切换也是因为异步事件未准备好,而主动让出的。这里的切换是没有任何代价,你可以理解为循环处理多个准备好的事件,事实上就是这样的。与多线程相比,这种事件处理方式是有很大的优势的,不需要创建线程,每个请求占用的内存也很少,没有上下文切换,事件处理非常的轻量级。并发数再多也不会导致无谓的资源浪费(上下文切换)。更多的并发数,只是会占用更多的内存而已。 我之前有对连接数进行过测试,在24G内存的机器上,处理的并发请求数达到过200万。现在的网络服务器基本都采用这种方式,这也是nginx性能高效的主要原因。

我们之前说过,推荐设置worker的个数为cpu的核数,在这里就很容易理解了,更多的worker数,只会导致进程来竞争cpu资源了,从而带来不必要的上下文切换。而且,nginx为了更好的利用多核特性,提供了cpu亲缘性的绑定选项,我们可以将某一个进程绑定在某一个核上,这样就不会因为进程的切换带来cache的失效。像这种小的优化在nginx中非常常见,同时也说明了nginx作者的苦心孤诣。比如,nginx在做4个字节的字符串比较时,会将4个字符转换成一个int型,再作比较,以减少cpu的指令数等等。

4、Nginx事件处理模型
类似与Libevent,通过epoll,IO复用机制,做到大量的高并发服务请求。

5、Nginx信号处理
对nginx来说,有一些特定的信号,代表着特定的意义。信号会中断掉程序当前的运行,在改变状态后,继续执行。如果是系统调用,则可能会导致系统调用的失败,需要重入。对于nginx来说,如果nginx正在等待事件(epoll_wait时),如果程序收到信号,在信号处理函数处理完后,epoll_wait会返回错误,然后程序可再次进入epoll_wait调用。判断epoll_wait的返回可以处理很多事情,例如处理信号、处理超时、处理连接中断

6、Nginx定时器处理
和Libevent的处理一模一样哦,只是Libevent将定时器事件放入了小根堆中。
epoll_wait等函数在调用的时候是可以设置一个超时时间的,所以nginx借助这个超时时间来实现定时器。nginx里面的定时器事件是放在一颗维护定时器的红黑树里面,每次在进入epoll_wait前,先从该红黑树里面拿到所有定时器事件的最小时间,在计算出epoll_wait的超时时间后进入epoll_wait。所以,当没有事件产生,也没有中断信号时,epoll_wait会超时,也就是说,定时器事件到了。这时,nginx会检查所有的超时事件,将他们的状态设置为超时,然后再去处理网络事件。由此可以看出,当我们写nginx代码时,在处理网络事件的回调函数时,通常做的第一个事情就是判断超时,然后再去处理网络事件。

一段伪代码来总结一下nginx的事件处理模型

while (true) {
    for t in run_tasks:
        t.handler();
    update_time(&now);
    timeout = ETERNITY;
    for t in wait_tasks: /* sorted already */
        if (t.time <= now) {
            t.timeout_handler();
        } else {
            timeout = t.time - now;
            break;
        }
    nevents = poll_function(events, timeout);
    for i in nevents:
        task t;
        if (events[i].type == READ) {
            t.handler = read_handler;
        } else { /* events[i].type == WRITE */
            t.handler = write_handler;
        }
        run_tasks_add(t);
}

3、Nginx配置通用语法

Nginx配置文件其实就是一个普通的文本文件。
下面是一个默认的配置文件,通过讲解这个,解释如何写配置文件。

#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;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
    listen  8011;
    server_name localhost;
    charset     utf-8;
    location / {
        alias    /home/wangjun/Desktop/test_space/;
    }
#    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;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #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;
    #    server_name  localhost;

    #    ssl                  on;
    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_timeout  5m;

    #    ssl_protocols  SSLv2 SSLv3 TLSv1;
    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers   on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}
}

1、块配置项
eventshttpserverlocation等都是块配置项。块配置项一定会用大括号把一系列所属的配置项全包含进来,表示大括号内的配置项同时生效。所有的事件类配置都要在events块中,httpserver等配置也遵循这个规定。块配置项可以嵌套。 内层块直接继承外层块, 例如,上例中,server块里的任意配置都是基于http块里的已有配置的。当内外层块中的配置发生冲突时, 究竟是以内层块还是外层块的配置为准, 取决于解析这个配置项的模块。

    server {  #块配置名 大括号开始, 通过空格将二者分开,
    listen  8011;  #配置项值,通过空格分开,可以是多条取决于解析的模块是否支持。
    server_name localhost; #每个配置的结尾通过;结束
    charset     utf-8;
    location / {
        alias    /home/wangjun/Desktop/test_space/;
    }

2、配置项单位
当指定空间大小,可以使用的单位包括如下:

  • K或k字节(KB)
  • M或m字节(MB)
  • ms、s、m、h、d、w、M、y(毫秒 秒 分 小时 周 月 年)

单位是否生效,取决于配置项的解析模块。

在执行configure命令时, 我们已经把许多模块编译进Nginx中, 但是否启用这些模块, 一般取决于配置文件中相应的配置项。 换句话说, 每个Nginx模块都有自己感兴趣的配置项, 大部分模块都必须在nginx.conf中读取某个配置项后才会在运行时启用。 例如, 只有当配置http{…}这个配置项时, ngx_http_module模块才会在Nginx中启用, 其他依赖ngx_http_module的模块也才能正常使用。

4、Nginx服务基本配置

Nginx在运行时, 至少必须加载几个核心模块和一个事件类模块。 这些模块运行时所支持的配置项称为基本配置——所有其他模块执行时都依赖的配置项。由于配置项较多,所以把它们按照用户使用时的预期功能
分成了以下4类。

1、用于调试、 定位问题的配置项
1)是否通过守护进程方式运行Nginx:
守护进程(daemon)是脱离终端并且在后台运行的进程。 它脱离终端是为了避免进程执行过程中的信息在任何终端上显示, 这样一来, 进程也不会被任何终端所产生的信息所打断。Nginx毫无疑问是一个需要以守护进程方式运行的服务,因此,默认都是以这种方式运行。Nginx还是提供了关闭守护进程的模式,之所以提供这种模式,是为了方便跟踪调试Nginx,毕竟用gdb调试进程时最烦琐的就是如何继续跟进fork出的子进程了。

语法:daemon on/off;
默认:daemon on;

2)是否以master/worker方式工作
Nginx通常以是以一个master进程管理多个worker进程的方式运行,这样可以实现高并发以及控制分离。与daemon配置相同,提master_process配置也是为了方便跟踪调试Nginx。 如果用关闭了master_process方式, 就不会fork出worker子进程来处理请求, 而是用master进程自身来处理请求,类似与Libevent的处理方式,通过单进程处理高并发请求。

语法:master_process on/off;
默认:master_process on;

3)error日志设置

语法:error_log  pathfile level;
默认:error_log  logs/error.log;

可以自由设置error日志的路径和级别。pathfile参数可以是一个具体的文件,默认是logs/error.log,最好将它放到一个磁盘空间足够大的位置,pathfile也可以是/dev/null, 这样就不会输出任何日志了,这也是关闭error日志的唯一手段。pathfile也可以是stderr, 这样日志会输出到标准错误文件中。

level是日志的输出级别,取值范围是debug、 info、 notice、 warn、error、crit、 alert、emerg从左至右级别依次增大。当设定为一个级别时, 大于或等于该级别的日志都会被输出到pathfile文件中, 小于该级别的日志则不会输出。 例如,当设定为error级别时,error、
crit、 alert、 emerg
级别的日志都会输出。如果设定的日志级别是debug, 则会输出所有的日志, 这样数据量会很大, 需要预先确保pathfile所在磁盘有足够的磁盘空间。日志级别设定到debug, 必须在configure时加入--with-debug配置项。

4)处理特殊调试点

语法: debug_points[stop|abort]

设定为stop那么Nginx的代码执行到这些调试点时就会发出SIGSTOP信号以用于调试。设定为abort,则会产生一个coredump文件, 可以使用gdb来查看Nginx当时的各种信息。通常不需要配置这项。

5)仅对指定的客户端输出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中配置的日志级别。上面这个配置对修复Bug很有用, 特别是定位高并发请求下才会发生的问题。

6)限制coredump核心转储文件的大小

语法: worker_rlimit_core size;

在Linux系统中,当进程发生错误或收到信号而终止时,系统会将进程执行时的内存内容(核心映像)写入一个文件(core文件),以作为调试之用,这就是所谓的核心转储(core dumps) 。当Nginx进程出现一些非法操作(如内存越界)导致进程直接被操作系统强制结束时,会生成核心转储core文件,可以从core文件获取当时的堆栈、 寄存器等信息,从而帮助我们定位问题。但这种core文件中的许多信息不一定是用户需要的,如果不加以限制,那么可能一个core文件会达到几GB,这样随便coredumps几次就会把磁盘占满,引发严重问题。 通过worker_rlimit_core配置可以限制core文件的大小,从而有效帮助用户定位问题。

7)指定coredump文件生成目录

语法: working_directory path;

worker进程的工作目录。这个配置项的唯一用途就是设置coredump文件所放置的目录,协助定位问题。因此,需确保worker进程有权限向working_directory指定的目录中写入文件。

以上7大调试策略,终究可以将Nginx的Bug定位出来。

2、正常运行的必备配置项

3、优化性能的配置项

4、事件类配置项
有些事件类配置项归纳到优化性能类,这是因为它们虽然也属于
events{}块, 但作用是优化性能。

1)是否打开accept锁
通过这个实现了负载均衡。

语法: accept_mutex[on|off]
默认: accept_mutext on;

accept_mutex是Nginx的负载均衡锁。accept_mutex这把锁可以让多个worker进程轮流地、序列化地与新的客户端建立TCP连接。 当某一个worker进程建立的连接数量达到worker_connections配置的最大连接数的7/8时,会大大地减小该worker进程试图建立新TCP连接的机会, 以此实现所有worker进程之上处理的客户端请求数尽量接近。accept锁默认是打开的, 如果关闭它,那么建立TCP连接的耗时会更短, 但是worker进程之间的负载会非常不均衡,因此不建议关闭它。

2)lock文件的路径

语法: lock_file path/file;
默认: lock_file logs/nginx.lock;

accept锁可能需要这个lock文件, 如果accept锁关闭, lock_file配置完全不生效。如果打开了accept锁,并且由于编译程序、 操作系统架构等因素导致Nginx不支持原子锁, 这时才会用文件锁实现accept锁,这样lock_file指定的lock文件才会生效。

3)使用accept锁后到真正建立连接之间的延迟时间

语法: accept_mutex_delay Nms;
默认: accept_mutex_delay 500ms;

在使用accept锁后,同一时间只有一个worker进程能够取到accept锁。 这个accept锁不是阻塞锁(Nginx拒绝阻塞调用),如果取不到会立刻返回。如果有一个worker进程试图取accept锁而没有取到, 它至少要等accept_mutex_delay定义的时间间隔后才能再次试图取锁。

(4) 批量建立新连接
语法: multi_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进程可以同时处理的最大连接数。

5、ngx_http_core_module

官方提供的英文文档

HTTP配置项自然必须全部在http{}块之内,http{}内可以包含server块location块upstream块或if块等。Nginx为配置一个完整的静态Web服务器提供了非常多的功能,包括以下8类:虚拟主机与请求的分发、文件路径的定义、内存及磁盘资源的分配、网络连接的设置、MIME类型的设置、对客户端请求的限制、文件操作的优化、对客户端请求的特殊处理。

1、虚拟主机与请求的分发

基于域名的虚拟主机是最常见的一种虚拟主机。只需配置你的DNS服务器,将每个主机名映射到正确的lP地址,然后配置Nginx服务器,令其识别不同的主机名就可以了。这种虚拟主机技术,使很多虚拟主机可以共享同一个lP地址,有效解决了lP地址不足的问题。所以,如果没有特殊要求使你必须用一个基于lP的虚拟主机,最好还是使用基于域名的虚拟主机。

1)监听端口,最好去看官方文档


Syntax: listen address[:port] [default_server] [ssl] [http2 | spdy] [proxy_protocol] [setfib=number] [fastopen=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind] [ipv6only=on|off] [reuseport] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]];

listen port [default_server] [ssl] [http2 | spdy] [proxy_protocol] [setfib=number] [fastopen=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind] [ipv6only=on|off] [reuseport] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]];

listen unix:path [default_server] [ssl] [http2 | spdy] [proxy_protocol] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]];
Default:    
listen *:80 | *:8000;
Context:    server

listen参数决定Nginx服务如何监听端口,在listen后可以只加IP地址、端口或主机名。

listen 127.0.0.1:8000;
listen 127.0.0.1;#默认采用80端口
listen 8000;
listen *:8000;
listen localhost:8000;

2)主机名称

Syntax: server_name name ...;
Default:    
server_name "";
Context:    server
server {
    server_name example.com www.example.com;
}

例如在上述虚拟主机配置多个主机名,当对应的主机域名到来时候,通过这个虚拟主机处理。在开始处理一个HTTP请求时, Nginx会取出header头中的Host, 与每个server中的server_name进行匹配, 以此决定到底由哪一个server块来处理这个请求。 有可能一个Host与多个server块中的server_name都匹配, 这时就会根据匹配优先级来选择实际处理的server块。

4)根据HTTP返回码重定向页面
语法: error_page code[code...][=|=answer-code]uri|@named_location

重定向:

当对于客户端某个请求返回错误码时,如果匹配上了error_page中设置code,则服务器端回应302临时重定向响应消息,其中重定向URL为error_page里面设定的location

例如有如下设置:

error_page 404 404.html;
error_page 502 503 504 50x.html;
error_page 403 http://example.com/forbidden.html
error_page 404 = @fetch;

虽然重定向了URI,但返回的HTTP错误码还是与原来的相同。用户可以通过“=”来更改返回的错误码。

error_page 404 =200 empty.gif;
error_page 404 =403 forbidden.gif;

也可以不指定确切的返回错误码,而是由重定向后实际处理的真实结果来决定,这时,只要把“=”后面的错误码去掉即可。

error_page 404 = /empty.gif;

如果不想修改URI,只是想让这样的请求重定向到另一个location中进行处理,那么可以这样设置。

location / (
    error_page 404 @fallback;
)
location @fallback (
    proxy_pass http://backend;
    )

这样, 返回404的请求会被反向代理到http://backend上游服务器中处理。
5)是否允许递归使用error_page

语法: recursive_error_pages[on|off];
默认: recursive_error_pages off;
确定是否允许递归地定义error_page

6)try_files

语法: try_files path1[path2] uri;

try_files后要跟若干路径,如path1 path2等而且最后必须要有URI参数,意义如下:请求到来服务端尝试按照顺序访问每一个path,如果可以有效地读取,就直接向用户返回这个path对应的文件结束请求, 否则继续向下访问。如果所有的path都找不到有效的文件,就重定向到最后的参数URI上。因此,最后这个参数URI必须存在,而且它应该是一个可以有效重定向的URI
例如:

try_files system/maintenance.html $uri $uri/index.html $uri.html @other;
location @other {
    proxy_pass http://backend;
    }
#如果前面的路径,如system/maintenance.html等,都找不到,就会反向代理到http://backend服务上。

location {
    try_files $uri $uri /error.phpc=404 =404;
}

2、文件路径的定义

3、内存及磁盘资源的分配

4、网络连接的设置

5、MIME类型的设置

6、对客户端请求的限制

7、文件操作的优化

8、对客户端请求的特殊处理

5、Nginx 方向代理模块配置项

官方提供的英文文档

参考:

Nginx开发从入门到精通
深入理解Nginx
http://nginx.org/en/docs/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有时需要偏执狂

请我喝咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值