久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

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

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

      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標(biāo)準(zhǔn)函數(shù) set_real_ip_from、real_ip_header
      最先執(zhí)行的 post-read 階段在 Nginx 讀取并解析完請求頭(request headers)之后就立即開始運行。標(biāo)準(zhǔn)模塊 ngx_realip 就在 post-read 階段注冊了處理程序,它的功能是迫使 Nginx 認(rèn)為當(dāng)前請求的來源地址是指定的某一個請求頭的值。下面這個例子就使用了 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 所指定的值。同時該例使用了標(biāo)準(zhǔn)內(nèi)建變量 $remote_addr 來輸出當(dāng)前請求的來源地址,以確認(rèn)是否被成功改寫。

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

      server-rewrite階段

      該階段包含標(biāo)準(zhǔn)函數(shù)ngx_rewrite、set 以及openresty函數(shù)set_by_lua、rewrite_by_lua
      post-read 階段之后便是 server-rewrite 階段。當(dāng) 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 核心來完成當(dāng)前請求與 location 配置塊之間的配對工作。

      location /hello {      echo "hello world";  }

      rewrite 階段

      該階段包含標(biāo)準(zhǔn)函數(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ì)上其實就是把當(dāng)前的請求處理階段強行倒退到 find-config 階段,以便重新進行請求 URI 與 location 配置塊的配對。比如例中,運行在 rewrite 階段的 rewrite 指令就讓當(dāng)前請求的處理階段倒退回了 find-config 階段。由于此時當(dāng)前請求的 URI 已經(jīng)被 rewrite 指令修改為了 /bar,所以這一次換成了 location /bar 與當(dāng)前請求相關(guān)聯(lián),然后再接著從 rewrite 階段往下執(zhí)行。
      為什么不直接在 rewrite 指令執(zhí)行時立即進行跳轉(zhuǎn)呢?
      為了在最初匹配的 location 塊中支持多次反復(fù)地改寫 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 階段

      該階段包含標(biāo)準(zhǔn)函數(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
      注意的是:標(biāo)準(zhǔn)模塊 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 階段遠(yuǎn)遠(yuǎn)晚于 post-read 階段執(zhí)行,所以在 post-read 階段,當(dāng)前請求還沒有和任何 location 相關(guān)聯(lián)。
      建議是:盡量在 server 配置塊中配置 ngx_realip 這樣的模塊

      post-access階段

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

      try-files 階段

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

       try_files /foo /bar/ =404;

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

      content階段

      該階段包含標(biāo)準(zhǔn)函數(shù)echo proxy_pass 以及openresty 函數(shù)content_by_lua balance_by_lua header_filter_by_lua body_filter_by_lua
      log

      所有請求的標(biāo)準(zhǔn)輸出都在改階段。幾乎所有的邏輯代碼也在改階段執(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)系”)。默認(rè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 階段只要有一個模塊通過了驗證,就會認(rèn)為請求整體通過了驗證,而在上例中, 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;  }

      為了進一步確認(rèn) 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 模塊先后看到當(dāng)前請求的 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,在確認(rèn)這兩個文件存在后,將它們的內(nèi)容分別作為響應(yīng)體輸出,并自動設(shè)置 Content-Type、Content-Length 以及 Last-Modified 等響應(yīng)頭。

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

      openresty請求處理順序

      set_by_lua: 流程分支處理判斷變量初始化
      rewrite_by_lua
      : 轉(zhuǎn)發(fā)、重定向、緩存等功能(例如特定請求代理到外網(wǎng))
      access_by_lua: IP 準(zhǔn)入、接口權(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í)行階段詳細(xì)解析

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