亚洲最大看欧美片,亚洲图揄拍自拍另类图片,欧美精品v国产精品v呦,日本在线精品视频免费

  • 站長資訊網(wǎng)
    最全最豐富的資訊網(wǎng)站

    Nginx執(zhí)行階段詳細解析

    Nginx 介紹
    Nginx (engine x) 是一個高性能的HTTP和反向代理服務(wù)器,也是一個IMAP/POP3/SMTP服務(wù)器。
    Nginx是一款輕量級的Web 服務(wù)器/反向代理服務(wù)器及電子郵件(IMAP/POP3)代理服務(wù)器,并在一個BSD-like 協(xié)議下發(fā)行。其特點是占有內(nèi)存少,并發(fā)能力強
    OpenResty介紹
    OpenResty 是一個基于 Nginx 與 Lua 的高性能 Web 平臺,其內(nèi)部集成了大量精良的 Lua 庫、第三方模塊以及大多數(shù)的依賴項。用于方便地搭建能夠處理超高并發(fā)、擴展性極高的動態(tài) Web 應(yīng)用、Web 服務(wù)和動態(tài)網(wǎng)關(guān)

    執(zhí)行階段前言

    location /test {  set $a 32;  echo $a;    set $a 56;  echo $a;  }

    兩次都會輸出56,因為set階段始終在content階段之前執(zhí)行,跟代碼的先后順序無關(guān)。

    Nginx執(zhí)行階段

    Nginx 處理請求的過程一共劃分為 11 個階段,按照執(zhí)行順序依次是 post-read、server-rewrite、find-config、rewrite、post-rewrite、preaccess、access、post-access、try-files、content 以及 log

    post-read 階段

    該階段Nginx標準函數(shù) set_real_ip_from、real_ip_header
    最先執(zhí)行的 post-read 階段在 Nginx 讀取并解析完請求頭(request headers)之后就立即開始運行。標準模塊 ngx_realip 就在 post-read 階段注冊了處理程序,它的功能是迫使 Nginx 認為當前請求的來源地址是指定的某一個請求頭的值。下面這個例子就使用了 ngx_realip 模塊提供的 set_real_ip_from 和 real_ip_header

    server {      listen 8080;      set_real_ip_from 127.0.0.1;      real_ip_header   X-My-IP;        location /test {          set $addr $remote_addr;          echo "from: $addr";      }  }

    這里的配置是讓 Nginx 把那些來自 127.0.0.1 的所有請求的來源地址,都改寫為請求頭 X-My-IP 所指定的值。同時該例使用了標準內(nèi)建變量 $remote_addr 來輸出當前請求的來源地址,以確認是否被成功改寫。

    $ curl -H 'X-My-IP: 1.2.3.4' localhost:8080/test      from: 1.2.3.4

    server-rewrite階段

    該階段包含標準函數(shù)ngx_rewrite、set 以及openresty函數(shù)set_by_lua、rewrite_by_lua
    post-read 階段之后便是 server-rewrite 階段。當 ngx_rewrite 模塊的配置指令直接書寫在 server 配置塊中時,基本上都是運行在 server-rewrite 階段。

    server {      listen 8080;        location /test {          set $b "$a, world";          echo $b;      }        set $a hello;  }

    這里,配置語句 set $a hello 直接寫在了 server 配置塊中,因此它就運行在 server-rewrite 階段。而 server-rewrite 階段要早于 rewrite 階段運行,因此寫在 location 配置塊中的語句 set $b “$a, world” 便晚于外面的 set $a hello 語句運行。該例的測試結(jié)果證明了這一點:

    $ curl localhost:8080/test  hello, world

    find-config 階段

    這個階段并不支持 Nginx 模塊注冊處理程序,而是由 Nginx 核心來完成當前請求與 location 配置塊之間的配對工作。

    location /hello {      echo "hello world";  }

    rewrite 階段

    該階段包含標準函數(shù)set_unescape_uri、rewrite以及openresty函數(shù)set_by_lua、 rewrite_by_lua

    post-rewrite 階段

    post-rewrite 階段,不接受 Nginx 模塊注冊處理程序,而是由 Nginx 核心完成 rewrite 階段所要求的“內(nèi)部跳轉(zhuǎn)”操作
    “內(nèi)部跳轉(zhuǎn)”的工作原理:本質(zhì)上其實就是把當前的請求處理階段強行倒退到 find-config 階段,以便重新進行請求 URI 與 location 配置塊的配對。比如例中,運行在 rewrite 階段的 rewrite 指令就讓當前請求的處理階段倒退回了 find-config 階段。由于此時當前請求的 URI 已經(jīng)被 rewrite 指令修改為了 /bar,所以這一次換成了 location /bar 與當前請求相關(guān)聯(lián),然后再接著從 rewrite 階段往下執(zhí)行。
    為什么不直接在 rewrite 指令執(zhí)行時立即進行跳轉(zhuǎn)呢?
    為了在最初匹配的 location 塊中支持多次反復地改寫 URI

        server {          listen 8080;            location /foo {              set $a hello;              rewrite ^ /bar;          }            location /bar {              echo "a = [$a]";          }      }
    location /foo {      rewrite ^ /bar;      rewrite ^ /baz;        echo foo;  }    location /bar {      echo bar;  }    location /baz {      echo baz;  }

    注意的:如果在 server 配置塊中直接使用 rewrite 配置指令對請求 URI 進行改寫,則不會涉及“內(nèi)部跳轉(zhuǎn)”

    server {  listen 8080;    rewrite ^/foo /bar;    location /foo {      echo foo;  }    location /bar {      echo bar;  }  }

    preaccess 階段

    該階段包含標準函數(shù)ngx_access-allow deny ngx_limit_req 和 ngx_limit_zone ngx_auth_request 以及openresty函數(shù)access_by_lua其中也包含了限頻限流模塊resty.limit.req resty.limit.conn
    注意的是:標準模塊 ngx_realip 其實也在這個階段注冊了處理程序

    server {      listen 8080;        location /test {          set_real_ip_from 127.0.0.1;          real_ip_header X-Real-IP;            echo "from: $remote_addr";      }  }

    與先看前到的例子相比,此例最重要的區(qū)別在于把 ngx_realip 的配置指令放在了 location 配置塊中。前面我們介紹過,Nginx 匹配 location 的動作發(fā)生在 find-config 階段,而 find-config 階段遠遠晚于 post-read 階段執(zhí)行,所以在 post-read 階段,當前請求還沒有和任何 location 相關(guān)聯(lián)。
    建議是:盡量在 server 配置塊中配置 ngx_realip 這樣的模塊

    post-access階段

    該階段不支持 Nginx 模塊注冊處理程序,而是由 Nginx 核心自己完成一些處理工作

    try-files 階段

    實現(xiàn)標準配置指令 try_files 的功能,并不支持 Nginx 模塊注冊處理程序。
    try_files 指令接受兩個以上任意數(shù)量的參數(shù),每個參數(shù)都指定了一個 URI. 這里假設(shè)配置了 N 個參數(shù),則 Nginx 會在 try-files 階段,依次把前 N-1 個參數(shù)映射為文件系統(tǒng)上的對象(文件或者目錄),然后檢查這些對象是否存在。一旦 Nginx 發(fā)現(xiàn)某個文件系統(tǒng)對象存在,就會在 try-files 階段把當前請求的 URI 改寫為該對象所對應(yīng)的參數(shù) URI(但不會包含末尾的斜杠字符,也不會發(fā)生 “內(nèi)部跳轉(zhuǎn)”)。如果前 N-1 個參數(shù)所對應(yīng)的文件系統(tǒng)對象都不存在,try-files 階段就會立即發(fā)起“內(nèi)部跳轉(zhuǎn)”到最后一個參數(shù)(即第 N 個參數(shù))所指定的 URI.

    location /test {      try_files /foo /bar/ /baz;      echo "uri: $uri";  }    location /foo {      echo foo;  }    location /bar/ {      echo bar;  }    location /baz {      echo baz;  }

    我們在 location /test 中使用了 try_files 配置指令,并提供了三個參數(shù),/foo、/bar/ 和 /baz. 根據(jù)前面對 try_files 指令的介紹,我們可以知道,它會在 try-files 階段依次檢查前兩個參數(shù) /foo 和 /bar/ 所對應(yīng)的文件系統(tǒng)對象是否存在。
    不妨先來做一組實驗。假設(shè)現(xiàn)在 /var/www/ 路徑下是空的,則第一個參數(shù) /foo 映射成的文件 /var/www/foo 是不存在的;同樣,對于第二個參數(shù) /bar/ 所映射成的目錄 /var/www/bar/ 也是不存在的。于是此時 Nginx 會在 try-files 階段發(fā)起到最后一個參數(shù)所指定的 URI(即 /baz)的“內(nèi)部跳轉(zhuǎn)”。實際的請求結(jié)果證實了這一點:

     $ curl localhost:8080/test     baz

    接下來再做一組實驗:在 /var/www/ 下創(chuàng)建一個名為 foo 的文件,其內(nèi)容為 hello world(注意你需要有 /var/www/ 目錄下的寫權(quán)限):

    $ echo 'hello world' > /var/www/foo

    然后再請求 /test 接口:

     $ curl localhost:8080/test    uri: /foo

    這里發(fā)生了什么?我們來看, try_files 指令的第一個參數(shù) /foo 可以映射為文件 /var/www/foo,而 Nginx 在 try-files 階段發(fā)現(xiàn)此文件確實存在,于是立即把當前請求的 URI 改寫為這個參數(shù)的值,即 /foo,并且不再繼續(xù)檢查后面的參數(shù),而直接運行后面的請求處理階段。
    通過前面這幾組實驗不難看到, try_files 指令本質(zhì)上只是有條件地改寫當前請求的 URI,而這里說的“條件”其實就是文件系統(tǒng)上的對象是否存在。當“條件”都不滿足時,它就會無條件地發(fā)起一個指定的“內(nèi)部跳轉(zhuǎn)”。當然,除了無條件地發(fā)起“內(nèi)部跳轉(zhuǎn)”之外, try_files 指令還支持直接返回指定狀態(tài)碼的 HTTP 錯誤頁,例如:

     try_files /foo /bar/ =404;

    這行配置是說,當 /foo 和 /bar/ 參數(shù)所對應(yīng)的文件系統(tǒng)對象都不存在時,就直接返回 404 Not Found 錯誤頁。注意這里它是如何使用等號字符前綴來標識 HTTP 狀態(tài)碼的。

    content階段

    該階段包含標準函數(shù)echo proxy_pass 以及openresty 函數(shù)content_by_lua balance_by_lua header_filter_by_lua body_filter_by_lua
    log

    所有請求的標準輸出都在改階段。幾乎所有的邏輯代碼也在改階段執(zhí)行。這個階段比較常見

    log階段

    改階段包含ngx的acces_log error_log以及openresty函數(shù)log_by_lua
    該階段主要記錄日志

    其它

    satisfy指令

    對于多個 Nginx 模塊注冊在 access 階段的處理程序, satisfy 配置指令可以用于控制它們彼此之間的協(xié)作方式。比如模塊 A 和 B 都在 access 階段注冊了與訪問控制相關(guān)的處理程序,那就有兩種協(xié)作方式,一是模塊 A 和模塊 B 都得通過驗證才算通過,二是模塊 A 和模塊 B 只要其中任一個通過驗證就算通過。第一種協(xié)作方式稱為 all 方式(或者說“與關(guān)系”),第二種方式則被稱為 any 方式(或者說“或關(guān)系”)。默認情況下,Nginx 使用的是 all 方式。

    location /test {      satisfy all;        deny all;      access_by_lua 'ngx.exit(ngx.OK)';        echo something important;  }

    如果我們把上例中的 satisfy all 語句更改為 satisfy any,

    location /test {      satisfy any;        deny all;      access_by_lua 'ngx.exit(ngx.OK)';        echo something important;  }

    結(jié)果則會完全不同:

    $ curl localhost:8080/test  something important

    在 any 方式下,access 階段只要有一個模塊通過了驗證,就會認為請求整體通過了驗證,而在上例中, ngx_lua 模塊的 access_by_lua 語句總是會通過驗證的。

    ngx_index 模塊, ngx_autoindex 模塊,以及 ngx_static 模塊

    Nginx 一般會在 content 階段安排三個這樣的靜態(tài)資源服務(wù)模塊。按照它們在 content 階段的運行順序,依次是 ngx_index 模塊, ngx_autoindex 模塊,以及 ngx_static 模塊。
    ngx_index 和 ngx_autoindex 模塊都只會作用于那些 URI 以 / 結(jié)尾的請求,例如請求 GET /cats/,而對于不以 / 結(jié)尾的請求則會直接忽略,同時把處理權(quán)移交給 content 階段的下一個模塊。而 ngx_static 模塊則剛好相反,直接忽略那些 URI 以 / 結(jié)尾的請求。
    ngx_index 模塊主要用于在文件系統(tǒng)目錄中自動查找指定的首頁文件,類似 index.html 和 index.htm 這樣的,例如:

    location / {      root /var/www/;      index index.htm index.html;  }

    為了進一步確認 ngx_index 模塊在找到文件時的“內(nèi)部跳轉(zhuǎn)”行為,我們不妨設(shè)計下面這個小例子:

    location / {      root /var/www/;      index index.html;  }    location /index.html {      set $a 32;      echo "a = $a";  }

    此時我們在本機的 /var/www/ 目錄下創(chuàng)建一個空白的 index.html 文件,并確保該文件的權(quán)限設(shè)置對于運行 Nginx worker 進程的帳戶可讀

    $ curl 'http://localhost:8080/'  a = 32

    如果此時把 /var/www/index.html 文件刪除,再訪問 / 又會發(fā)生什么事情呢?答案是返回 403 Forbidden 出錯頁。為什么呢?因為 ngx_index 模塊找不到 index 指令指定的文件(在這里就是 index.html),接著把處理權(quán)轉(zhuǎn)給 content 階段的后續(xù)模塊,而后續(xù)的模塊也都無法處理這個請求,于是 Nginx 只好放棄,輸出了錯誤頁
    運行在 ngx_index 模塊之后的 ngx_autoindex 模塊就可以用于自動生成這樣的“目錄索引”網(wǎng)頁。我們來把上例修改一下:

    location / {      root /var/www/;      index index.html;      autoindex on;  }

    此時仍然保持文件系統(tǒng)中的 /var/www/index.html 文件不存在。我們再訪問 / 位置時,就會得到一張漂亮的網(wǎng)頁:

    $ curl 'http://localhost:8080/'

    ngx_static 模塊服務(wù)磁盤文件的例子。我們使用下面這個配置片段:
    location / {
    root /var/www/;
    }

    現(xiàn)在來通過 HTTP 協(xié)議請求一下這兩個文件所對應(yīng)的 URI:

    $ curl 'http://localhost:8080/index.html'  this is my home    $ curl 'http://localhost:8080/hello.html'  hello world

    location / 中沒有使用運行在 content 階段的模塊指令,于是也就沒有模塊注冊這個 location 的“內(nèi)容處理程序”,處理權(quán)便自動落到了在 content 階段“墊底”的那 3 個靜態(tài)資源服務(wù)模塊。首先運行的 ngx_index 和 ngx_autoindex 模塊先后看到當前請求的 URI,/index.html 和 /hello.html,并不以 / 結(jié)尾,于是直接棄權(quán),將處理權(quán)轉(zhuǎn)給了最后運行的 ngx_static 模塊。ngx_static 模塊根據(jù) root 指令指定的“文檔根目錄”(document root),分別將請求 URI /index.html 和 /hello.html 映射為文件系統(tǒng)路徑 /var/www/index.html 和 /var/www/hello.html,在確認這兩個文件存在后,將它們的內(nèi)容分別作為響應(yīng)體輸出,并自動設(shè)置 Content-Type、Content-Length 以及 Last-Modified 等響應(yīng)頭。

    很多初學者會想當然地把 404 錯誤理解為某個 location 不存在,其實上面這個例子表明,即使 location 存在并成功匹配,也是可能返回 404 錯誤頁的。因為決定著 404 錯誤頁的是抽象的“資源”是否存在,而非某個具體的 location 是否存在。
    location /auth {
    access_by_lua ‘
    ‘;
    }
    顯然,這個 /auth 接口只定義了 access 階段的配置指令,即 access_by_lua,并未定義任何 content 階段的配置指令。于是當我們請求 /auth 接口時,在 access 階段的 Lua 代碼會如期執(zhí)行,然后 content 階段的那些靜態(tài)文件服務(wù)會緊接著自動發(fā)生作用,直至 ngx_static 模塊去文件系統(tǒng)上找名為 auth 的文件。而經(jīng)常地,404 錯誤頁會拋出,除非運氣太好,在對應(yīng)路徑上確實存在一個叫做 auth 的文件。所以,一條經(jīng)驗是,當遇到意外的 404 錯誤并且又不涉及靜態(tài)文件服務(wù)時,應(yīng)當首先檢查是否在對應(yīng)的 location 配置塊中恰當?shù)嘏渲昧?content 階段的模塊指令,例如 content_by_lua、 echo 以及 proxy_pass 之類。

    openresty請求處理順序

    set_by_lua: 流程分支處理判斷變量初始化
    rewrite_by_lua
    : 轉(zhuǎn)發(fā)、重定向、緩存等功能(例如特定請求代理到外網(wǎng))
    access_by_lua: IP 準入、接口權(quán)限等情況集中處理(例如配合 iptable 完成簡單防火墻)
    content_by_lua
    : 內(nèi)容生成
    header_filter_by_lua: 響應(yīng)頭部過濾處理(例如添加頭部信息)
    body_filter_by_lua
    : 響應(yīng)體過濾處理(例如完成應(yīng)答內(nèi)容統(tǒng)一成大寫) log_by_lua*:會話完成后本地異步完成日志記錄(日志可以記錄在本地,還可以同步到其他機器)

    Nginx執(zhí)行階段詳細解析

    贊(0)
    分享到: 更多 (0)
    網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號