Einführung in die Nginx-Phasen

WBOY
Freigeben: 2016-08-08 09:27:31
Original
1189 Leute haben es durchsucht
1. Die 11 Phasen von Nginx

Wenn eine Anfrage von Nginx verarbeitet wird, durchläuft sie eine Reihe von Phasen (Phasen). optionale Exit-Methoden für jede Phase, enthaltene Module und entsprechende Anweisungen

phase optional exits modules / directives description
NGX_HTTP_POST_READ_PHASE   HttpRealIpModule 读取请求内容阶段
NGX_HTTP_SERVER_REWRITE_PHASE (server rewrite)   HttpRewriteModule / rewrite 请求地址重写阶段
NGX_HTTP_FIND_CONFIG_PHASE(location selection)   HttpCoreModule / location 配置查找阶段
NGX_HTTP_REWRITE_PHASE Location(location rewrite) location selection, 
finalize request
HttpRewriteModule / rewrite 请求地址重写阶段
NGX_HTTP_POST_REWRITE_PHASE   HttpRewriteModule / rewrite 请求地址重写提交阶段
NGX_HTTP_PREACCESS_PHASE   degradation, NginxHttpLimitZoneModule / limit_zone, 
HttpLimitReqModule / limit req, HttpRealIpModule
访问权限检查准备阶段
NGX_HTTP_ACCESS_PHASE finalize request HttpAccessModule / allow, deny, NginxHttpAuthBasicModule / auth_basic 访问权限检查阶段
NGX_HTTP_POST_ACCESS_PHASE     访问权限检查提交阶段
NGX_HTTP_TRY_FILES_PHASE location selection HttpCoreModule / try_files 配置项try_files处理阶段
NGX_HTTP_CONTENT_PHASE   HttpAutoindexModule / autoindex,HttpCoreModule / Core, HttpDavModule / DAV,
HttpEmptyGifModule / EmptyGif, HttpFcgiModule / FastCGI, HttpFlvStreamModul / FLV, 
HttpGzipStaticModule / gzip_static, HttpIndexModule / index,
HttpMemcachedModule / memcached, EmbeddedPerlModule / perl,
HttpProxyModule / proxy, HttpProxyModule / random_index,
HttpScgiModule / scgi, HttpStubStatusModule / stub_status, 
HttpUwsgiModule / uwsgi HttpLuaModule / content_by_lua,
HttpCoreModule / proxy_pass
内容产生阶段
NGX_HTTP_LOG_PHASE   HttpLogModuel / access_log 日志模块处理阶段
2. Beschreibung jeder Phase:
Post-Read-Phase:

Nach dem Lesen des Anforderungsheaders geht es in die Post-Read-Phase. Diese Phase ermöglicht es Nginx, den Wert der IP-Adresse im Anforderungsheader zu ändern. Das zugehörige Modul HttpRealIpModule.

server_rewrite Phase:

In dieser Phase geht es hauptsächlich um die Initialisierung globaler Variablen oder das Umschreiben auf Serverebene. Wenn der Rewrite-Befehl auf dem Server platziert wird, wird die Server-Rewrite-Phase gestartet. (Anweisungen zum Umschreiben finden Sie in der Umschreibephase)

Konfigurationsphase finden:

Diese Phase verwendet die umgeschriebene URL, um den entsprechenden Speicherort zu finden Beachten Sie, dass diese Phase möglicherweise mehrmals ausgeführt wird, da möglicherweise auch Umschreibungsanweisungen auf Standortebene vorhanden sind.

Rewrite-Phase:

Wenn Sie die Rewrite-Anweisung an der Position platzieren, gelangen Sie in die Rewrite-Phase, die sich an der Position befindet In der URI-Umschreibungsphase können die Umschreibungsanweisungen auch mehrmals ausgeführt werden.

Die Umschreibungsanweisungen umfassen die Set-Anweisung und die Rewrite-Anweisung von HttpRewriteModule, die set_by_lua-Anweisung von HttpLuaModule und die set_unescape_uri-Anweisung des ngx_set_misc-Moduls Und fast alle HttpRewriteModule Die Anweisungen gehören alle zur Rewrite-Phase.

Lassen Sie uns an dieser Stelle über eine Frage nachdenken: Können diese Anweisungen an derselben Stelle koexistieren, da sie in dieser Phase neu geschrieben werden können?

Beispiel 1:
Denken Sie über die Ausgabe des folgenden Beispiels nach. Was ist das Ergebnis?

 location /test {
        set $a 32;
        set $b 56;
        set_by_lua $c "return ngx.var.a + ngx.var.b";
        set $d "$a + $b = $c";
        echo $d;
    }
Nach dem Login kopieren

Wenn wir auf http://localhost/test zugreifen, ist die Ausgabe 32 + 56 = 88, was unseren Erwartungen entsprechen sollte.

Dies beweist jedoch nicht, dass alle Anweisungen verschiedener Module, die zu denselben Phasen gehören, in der richtigen Reihenfolge ausgeführt werden müssen, wenn sie in einer Phase koexistieren. Tatsächlich verwenden die oben genannten Module von Drittanbietern alle spezielle Techniken, um ihre eigenen Konfigurationsanweisungen in die Befehlssequenz von HttpRewriteModule zu „einzufügen“ (sie alle verwenden das von Marcus Clyne geschriebene Modul ngx_devel_kit eines Drittanbieters). Mit anderen Worten: Konventionelleres Umschreiben in Nginx Module von Drittanbietern, die die Registrierung durchführen und Anweisungen ausführen, haben nicht so viel Glück. Obwohl die Anweisungen dieser „regulären Module“ auch in der Rewrite-Phase ausgeführt werden, werden ihre Konfigurationsanweisungen und HttpRewriteModule (und andere Module in derselben Phase) unabhängig voneinander ausgeführt. Zur Laufzeit ist die Reihenfolge zwischen den Konfigurationsbefehlssätzen verschiedener Module im Allgemeinen ungewiss (streng genommen wird sie im Allgemeinen durch die Ladereihenfolge der Module bestimmt, es gibt jedoch Ausnahmen). Beispielsweise führen beide Module A und B Anweisungen in der Umschreibephase aus, sodass entweder alle Anweisungen von Modul A ausgeführt werden, bevor die Anweisungen von Modul B ausgeführt werden, oder umgekehrt, alle Anweisungen von Modul B ausgeführt werden und dann A ausgeführt wird Anweisungen ausgeführt. Sofern in der Dokumentation des Moduls nicht ausdrücklich angegeben, sollten Benutzer im Allgemeinen keine Konfigurationen schreiben, die auf dieser unbestimmten Reihenfolge basieren. Es gibt auch viele Module von Drittanbietern, ngx_array_var Und ngx_encrypted_session, das zum Ver- und Entschlüsseln von Benutzersitzungen verwendet wird, kann auch nahtlos mit den Anweisungen von HttpRewriteModule zusammenarbeiten. Das Standard-HttpRewriteModule ist so weit verbreitet, dass Module von Drittanbietern, die mit seinen Konfigurationsanweisungen gemischt werden können, von Vorteil sind. Anweisungen, die nicht mit HttpRewriteModule gemischt werden können, sollten bei der tatsächlichen Verwendung beachtet werden. Ihre Ausgabe ist undefiniert, was nichts mit ihrer Reihenfolge in der Konfigurationsdatei zu tun hat.

Fazit: Anweisungen mit Bereichen in verschiedenen Modulen derselben Phase. Wenn besondere Kompatibilität zwischen Modulen hergestellt wird, werden sie nacheinander in der Reihenfolge ausgeführt, in der die Anweisungen in der Konfigurationsdatei erscheinen

Beispiel 2:
Überlegen Sie, wie die Ausgabe unten aussieht?

location /test {
        set $value dog;
        more_set_input_headers "X-Species: $value";
        set $value cat;
        echo "X-Species: $http_x_species";
    }
Nach dem Login kopieren

访问:curl 'http://localhost/test'
输出:X-Species: cat
是不是和你的预期有点儿不一样呢?

说明:第三方模块 ngx_headers_more 提供了一系列配置指令,用于操纵当前请求的请求头和响应头。其中有一条名叫 more_set_input_headers 的指令可以在 rewrite 阶段改写指定的请求头(或者在请求头不存在时自动创建)。该指令的文档中有这么一行标记 phase: rewrite tail,是说这条指令总是运行在 rewrite 阶段的末尾。显然,写在 more_set_input_headers 指令之后的 set $value cat 语句却先执行了。也就是说属于HttpRewriteModule的set指令先执行完了,才执行ngx_header_more 的set_input_headers指令。
结论:即使运行在同一个请求处理阶段,分属不同模块的配置指令也可能会分开独立运行(除非像 ngx_set_misc 等模块那样针对 ngx_rewrite 模块提供特殊支持)。换句话说,在单个请求处理阶段内部,一般也会以 Nginx 模块为单位进一步地划分出内部子阶段。下面的例子3同例子2:

例子3:

location /test {
         set $a 1;
         rewrite_by_lua "ngx.var.a = ngx.var.a + 1";
         set $a 56;    
         echo $a;
     }
Nach dem Login kopieren

访问: curl 'http://localhost/test'
输出: 57

说明:HttpLuaModule的rewrite_by_lua 指令也是处在 rewrite tail phase,它也会在rewrite 阶段的末尾执行。因此HttpRewriteModule的所有set执行完后,才执行它。
显然,rewrite_by_lua 指令的行为不同于我们前面在 (二) 中介绍过的 set_by_lua 指令。
小伙伴们可能要问,既然 more_set_input_headers 和 rewrite_by_lua 指令都运行在 rewrite 阶段的末尾,那么它们之间的先后顺序又是怎样的呢?答案是:不一定。我们应当避免写出依赖它们二者间顺序的配置。

结论:作用域在同一个phase的不同modules的指令,如果没有做特殊兼容处理,则它们指令的执行顺序与指令在配置中出现的顺序无关,结果具有不确定性

post rewrite phase:

location级别重写的下一阶段,用来检查上阶段是否有uri重写,并根据结果跳转到合适的阶段;

preaccess phase:

访问权限控制的前一阶段,该阶段在权限控制阶段之前,一般也用于访问控制,比如限制访问频率,链接数等;相关模块/指令 :NginxHttpLimitZoneModule / limit_zone, 
HttpLimitReqModule / limit req, HttpRealIpModule

access phase:

访问权限控制阶段,比如基于ip黑白名单的权限控制,基于用户名密码的认证控制等;相关模块/指令 HttpAccessModule / allow, deny, NginxHttpAuthBasicModule / auth_basic。 HttpAccessModule提供的 allow 和 deny 配置指令可用于控制哪些 IP 地址可以访问,哪些不可以。HttpAccessModule模块还支持所谓的“CIDR 记法”来表示一个网段,例如 169.200.179.4/24 则表示路由前缀是 169.200.179.0(或者说子网掩码是 255.255.255.0)的网段。

思考下下面两个例子(例子5,例子6)
例子4:

    location /hello {
        allow 127.0.0.1;
        deny all; 
        echo "hello world";
    }
Nach dem Login kopieren

本机访问:curl http://localhost/hello ,输出:hello world
其他机器访问:curl http://localhost/hello ,报403错误

例子5:

    location /hello {
        deny all; 
        allow 127.0.0.1;
        echo "hello world";
    }
Nach dem Login kopieren

本机访问:curl http://localhost/hello ,报403错误
其他机器访问:curl http://localhost/hello ,报403错误

例5和例6的区别在于deny all ,和allow 127.0.0.1 这两条指令的顺序不同。但例5中/hello 只允许从本机(IP 地址为保留的 127.0.0.1)访问,而从其他 IP 地址访问都会被拒(返回 403 错误页)。而例6中被配置为任何IP访问都会返回403错误。
原因说明:同属于HttpAccessModule这个模块的多条配置指令之间是按顺序执行的,直到遇到第一条满足条件的指令就不再执行后续的 allow 和 deny 指令。如果首先匹配的指令是 allow,则会继续执行后续其他模块的指令或者跳到后续的处理阶段;而如果首先满足的是 deny 则会立即中止当前整个请求的处理,并立即返回给客户端 403 错误页。

结论:同一个phase的同一个module内的多条指令的执行顺序由这个module自己来定义。

因为 HttpAccessModule的指令运行在 access 阶段,而 access 阶段又处于 rewrite 阶段之后,所以前面我们见到的所有那些在 rewrite 阶段运行的配置指令,都总是在 allow 和 deny 之前执行,而无论它们在配置文件中的书写顺序是怎样的。所以,为了避免阅读配置时的混乱,我们应该总是让指令的书写顺序和它们的实际执行顺序保持一致。

post access phase:

访问权限控制的后一阶段,该阶段根据权限控制阶段的执行结果进行相应处理;

try files phase:

HttpCoreModule的try_files指令的处理阶段,如果没有配置try_files指令,则该阶段被跳过; 该指令作用域: server ,location。
当try_files用于server阶段时一般是初始化作用,用来加载一些文件。

语法: try_files file1,file2,..,fileN-1 ... ,fallback 或者try_files file1,file2,..,fileN = code
用来顺序检查file1,file2,...fileN-1是否存在,如果最后一个字符为/表示这是一个目录。只要找到一个file存在,则进入到content phase,输出内容。如果前N-1个参数代表的file都不存在,此时最后一个参数发挥作用,最后一个参数用于内部跳转,并且只有最后一个参数是用作内部跳转,因此最后一个参数必须存在,否则将会引发一个内部错误。前面的file参数只是设置uri指向,不会引发内部跳转。此外注意: try_files和rewrite不同,rewrite指令会自动保存原请求的参数$args,而try_files最后的fallback参数如果需要带上请求的参数,则需要明确指出,如:

try_files $uri $uri/ /index.php?q=$uri&$args
Nach dem Login kopieren
content phase:

内容生成阶段,该阶段产生响应,并发送到客户端; 这个阶段相关的模块和指令较多。这里仅拿HttpLuaModule的content_by_lua和HttpEchoModule的echo指令来举个例子再次证明上述谈论到的一个结论。
例子:

 location /test {
          set $a 123;
          set $b 456;
          echo $b;
          content_by_lua '
             ngx.say(ngx.var.a)
           ';
    }
Nach dem Login kopieren

访问: curl http://localhost/test
输出: 123 
即只有content_by_lua里面的ngx.say执行了,外面的echo $b指令没有执行。echo和content_by_lua分别属于两个module的指令,他们的作用phase都是content phase。这两个module不兼容,
这两条指令不是顺序执行,至于执行结果是什么,不确定,这里是只有content_by_lua被执行了。再次证明之前的结论:作用域在同一个phase的不同modules的指令,如果没有做特殊兼容处理,则它们指令的执行顺序与指令在配置中出现的顺序无关,结果具有不确定性,需要尽量避免这种情况出现。
 location /test_echo {
          content_by_lua '
             ngx.say(ngx.var.a)
           ';
          set $a 123;
          set $b 456;
    }
Nach dem Login kopieren
log phase:

日志记录阶段,该阶段记录访问日志;

三、小结:
  • 11个phases粗略介绍完了。这11个phases,不是每个请求都会经历所有的11个phase。有可能某些phase没有经历,如果请求内部包含子请求,某些phase可能会出现多次。
  • 在单个请求的处理过程中,前面的phase总是在后面phase之前执行。这里的前后值得是本文phase的介绍顺序,而不是phase相关的指令在配置文件中出现的顺序。
    例如,rewrite phase总是在content phase之前执行,与指令在配置文件中出现顺序无关,下面的例子
    location /test {
        set $a 11;
        echo $a; 
        set $a 22;
        echo $a;
    }
    
    Nach dem Login kopieren

    实际执行顺序为set $a 11;set $a 22;echo $a;echo $a;
    访问:curl http://localhost/test
    输出:
    22 
    22
    理由是rewrite phase总是在content phase之前执行
  • 作用域为同一个phase的不同modules的指令,如果modules之间做了特殊的兼容,则它们按照指令在配置文件中出现的顺序依次执行下来
  • 作用域在同一个phase的不同modules的指令,如果没有做特殊兼容处理,则它们指令的执行顺序与指令在配置中出现的顺序无关,结果具有不确定性
  • 同一个phase的同一个module内的多条指令的执行顺序由这个module自己来定义。

参考资料:

http://wiki.nginx.org/

http://wiki.nginx.org/Phases

http://blog.sina.com.cn/s/blog_6d579ff40100xpff.html

Das Obige ist eine Einführung in die Nginx-Phase, einschließlich der relevanten Inhalte. Ich hoffe, dass es für Freunde hilfreich ist, die sich für PHP-Tutorials interessieren.

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage