Nginx與X-Sendfile


X-accel模塊允許由后台通過返回的頭來決定投遞靜態文件。為什么要這么做呢?試想一下我們經常碰到的這種情況,在有的論壇中,下載資源需要登錄認證、權限核查、積分扣除或者是積分增加等等,對於Nginx來說這些細粒度的控制其本身無法完成,因此需要應用程序來完成,當應用程序完成這些操作后,根據實際情況會做出選擇,如果條件滿足那么開始下載所要獲取的靜態資源(文件),注意,這是由動態的程序提供下載,對於動態程序來說,這是一個弱點,而對於Nginx來說,這是它的強項,那么在這種形式下能不能讓Nginx來完成靜態資源的下載呢?答案是可以的。但我們為什么有必要這么做呢?答案在於Nginx在打開靜態文件上使用了sendfile(2),因此其IO效率非常之高。

 

處理流程

 

    具體的處理流程是:

 

   

     -------------------------

     |"GET /dd/filename  |

     |                           |

    ∨                          |

  客戶端請求----------->Nginx----->Backend(Apache、Tomcat、FastCGI,……)

                               ∧                                                                |

                                |                                                                 |

                                |  X-Accel-Redirect: /files/filename                   |

                                |_______________________________________|

  

    我們從這個流程圖中不難看出在客戶端的請求被轉向后台服務器時,服務器並沒有為客戶端返回實際要下載的資源(而是去做了其它的驗證或者是其它的工作)而是使用了X-Accel-Redirect頭將下載的資源又傳遞給了Nginx,最后又是通過Nginx服務器處理該請求發送給客戶端。

 

    這種功能就是我們說的X-Sendfile,在Nginx中由X-Accel-Redirect來完成,在后台服務器將下載的請求拋給Nginx后,那么后台的服務器又可以承接其它的活進而處理其它的請求了,因此大大的減輕了后端服務器的壓力。

 

    相對於其它的Nginx來說,X-accel模塊與其它標准的Nginx模塊有所不同,它的實現不是依賴於指令而是依賴於在特定方式下后台(或者叫上游)服務器發回的請求頭,它的方法我們在前面也了解到了,就是通過發送一個帶有URI的x-accel-redirect頭,Nginx將會將這個請求作為正常(這里的正常就是指就像是使用瀏覽器一樣的請求)的請求來處理這個請求,然后根據這個URI進行location匹配,然后是請求文件的匹配,最終實現的是在后端服務器返回的請求頭中:“root + URI”與Nginx中location匹配,這里的“root”,我們以PHP程序為例:

 

header("X-Accel-Redirect: /files/" . $path);

   

    就是我們這個PHP程序中的“/files/”部分,而URI則是“$path”部分。在這里我們就了解到這里,在后面的例子會證實這一點。

 

    另外,還需要注意一點,由於Nginx服務器只認識從后端服務器發來的X-Accel-Redirect頭,而從客戶端發來的這種頭,它並不理睬。

 

配置示例

 

# Will serve /var/www/files/myfile.tar.gz

# When passed URI /protected_files/myfile.tar.gz

location /protected_files {

    internal;

    alias /var/www/files;

}

 

# Will serve /var/www/protected_files/myfile.tar.gz

# When passed URI /protected_files/myfile.tar.gz

location /protected_files {

    internal;

    root /var/www;

}

 

You can also proxy to another server.

 

location /protected_files {

    internal;

    proxy_pass http://127.0.0.2;

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM