nginx 단계 소개

WBOY
풀어 주다: 2016-08-08 09:27:31
원래의
1188명이 탐색했습니다.
1. nginx의 11단계

nginx에서 요청을 처리할 때 일련의 단계(단계)를 거치게 됩니다. 다음 표에는 모든 nginx 단계가 나열되어 있습니다. 각 단계에 대한 선택적 종료 방법, 포함된 모듈 및 해당 지침

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. 각 단계 설명:
포스트 읽기 단계:

요청 헤더를 읽은 후 post_read 단계로 들어갑니다. URI가 다시 작성되기 전에 이 단계를 통해 nginx는 관련 모듈 HttpRealIpModule.

server_rewrite에서 IP 주소 값을 변경할 수 있습니다. 단계:

이 단계에는 주로 전역 변수 초기화 또는 서버 수준 재작성이 포함됩니다. 다시 쓰기 명령이 서버에 배치되면 서버 다시 쓰기 단계로 들어갑니다. (다시 쓰기 지침은 다시 쓰기 단계 참조)

찾기 구성 단계:

이 단계에서는 다시 작성된 URI를 사용하여 해당 위치를 찾습니다. 위치 수준 다시 쓰기 명령이 있을 수도 있으므로 이 단계가 여러 번 실행될 수 있다는 점은 주목할 가치가 있습니다.

다시 쓰기 단계:

다시 쓰기 명령을 해당 위치에 넣으면 해당 위치에 있는 다시 쓰기 단계로 들어갑니다. 레벨 재작성 단계에서는 재작성 명령이 여러 번 실행될 수도 있습니다.

재작성 명령에는 HttpRewriteModule의 set 명령 및 다시 쓰기 명령, HttpLuaModule의 set_by_lua 명령, ngx_set_misc 모듈의 set_unescape_uri 명령이 포함됩니다. 거의 모든 HttpRewriteModule 지침은 모두 다시 쓰기 단계에 속합니다.

이 시점에서 생각해 봅시다. 이 단계에서 다른 모듈을 사용하지 않고도 명령어를 다시 작성할 수 있으므로 이러한 명령어가 동일한 위치에 공존할 수 있습니까? 그렇다면 실행 순서는 무엇입니까?

예제 1:
다음 예의 결과를 생각해 보세요.

 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;
    }
로그인 후 복사

http://localhost/test에 접속하면 32가 출력됩니다. + 56 = 88, 이는 우리의 기대와 일치해야 합니다.

그러나 이는 동일한 단계에 속하는 서로 다른 모듈의 명령이 한 단계에 공존할 때 순서대로 모두 실행되어야 한다는 것을 증명하지는 않습니다. 실제로 위에서 언급한 타사 모듈은 모두 특별한 기술을 사용하여 자체 구성 지침을 HttpRewriteModule의 명령 시퀀스에 "주입"합니다(모두 Marcus Clyne이 작성한 타사 모듈 ngx_devel_kit을 사용함). 즉, Nginx에서 보다 일반적인 재작성을 수행합니다. 등록을 준비하고 지침을 실행하는 타사 모듈은 그다지 운이 좋지 않습니다. 이러한 "일반 모듈"의 명령도 다시 쓰기 단계에서 실행되지만 해당 구성 명령과 HttpRewriteModule(및 동일한 단계의 다른 모듈)은 독립적으로 실행됩니다. 런타임 시 서로 다른 모듈의 구성 명령 세트 간의 순서는 일반적으로 불확실합니다(엄밀히 말하면 일반적으로 모듈의 로드 순서에 따라 결정되지만 예외도 있습니다). 예를 들어, 모듈 A와 B는 모두 다시 쓰기 단계에서 명령어를 실행하므로 모듈 B의 명령어를 실행하기 전에 모듈 A의 모든 명령어가 실행되거나, 그 반대로 모듈 B의 모든 명령어가 실행된 다음 A가 실행됩니다. 지시가 실행되었습니다. 모듈 문서에 명시적으로 언급되지 않은 한, 사용자는 일반적으로 이 불확실한 순서에 의존하는 구성을 작성해서는 안 됩니다. 타사 모듈인 ngx_array_var도 많이 있습니다. 그리고 사용자 세션을 암호화하고 해독하는 데 사용되는 ngx_encrypted_session도 HttpRewriteModule의 명령과 원활하게 작동할 수 있습니다. 표준 HttpRewriteModule은 매우 널리 사용되므로 해당 구성 지시문과 혼합할 수 있는 타사 모듈이 다행입니다. HttpRewriteModule과 혼합할 수 없는 지침은 실제 사용 중에 기록되어야 합니다. 출력은 정의되지 않으며 이는 구성 파일의 순서와 관련이 없습니다.

결론: 동일한 단계의 다른 모듈에 범위가 있는 명령어가 모듈 간에 특별한 호환성이 있으면 구성 파일에 명령어가 나타나는 순서대로 순차적으로 실행됩니다.

예시 2:
아래 출력이 무엇인지 생각해 보세요.

location /test {
        set $value dog;
        more_set_input_headers "X-Species: $value";
        set $value cat;
        echo "X-Species: $http_x_species";
    }
로그인 후 복사

访问: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;
     }
로그인 후 복사

访问: 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";
    }
로그인 후 복사

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

例子5:

    location /hello {
        deny all; 
        allow 127.0.0.1;
        echo "hello world";
    }
로그인 후 복사

本机访问: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
로그인 후 복사
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)
           ';
    }
로그인 후 복사

访问: 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;
    }
로그인 후 복사
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;
    }
    
    로그인 후 복사

    实际执行顺序为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

위 내용은 관련 내용을 포함한 nginx 단계에 대한 소개입니다. PHP 튜토리얼에 관심이 있는 친구들에게 도움이 되길 바랍니다.

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿