使用nginx的XSendfile提升php下載檔案效能
我在之前一篇筆記裡面寫了如何用php下載檔案,裡面寫了兩種方法來下載檔案
- nginx配置直接try_files下載檔案
- php讀取檔案之後再輸出
對於第二種方法,php-fpm和nginx的記憶體和IO情況都有飆升。
在傳統的檔案傳輸過程中,檔案資料經歷了以下步驟:
硬碟 -> 核心buffer -> 使用者buffer -> socket相關緩衝區 -> 協議棧
而sendfile機制被開啟之後,減少了一次檔案copy,提升了檔案傳輸效能,檔案資料經歷的步驟如下:
硬碟 -> 核心buffer -> socket相關緩衝區 -> 協議棧
在當前流行的幾個web伺服器(apache、nginx、lighttpd等)裡面,都有關於sendfile的配置。
下面說說如何使用nginx的XSendfile來提升PHP檔案下載效能。
關於nginx的XSendfile的詳細內容可以看官方文件
1. nginx開啟sendfile
在nginx.conf裡面,設定sendfile on
表示開啟sendfile機制
2. 配置路由規則
location /protectedFile/ { internal; root/home/nemo/fileDir; }
internal
表示這個路徑只能在nginx內部訪問,不能在瀏覽器裡面被訪問。
配置完之後,重啟nginx。
3. 修改php程式碼
<?php checkAuthority(); // 做一些業務相關的使用者鑑權相關的操作 …… …… $filePath = '/protectedFile/test.pdf'; header('Content-type: application/octet-stream'); header('Content-Disposition: attachment; filename="' . basename($filePath) . '"'); // 讓Xsendfile傳送檔案 header('X-Accel-Redirect: '.$filePath); ?>
在php程式碼裡面使用X-Accel-Redirect
讓nginx使用XSendfile機制提升下載效能,這樣使用者下載到了/home/nemo/fileDir/protectedFile/test.pdf
檔案
比較一下使用與不使用XSendfile,下載一份20MB+的檔案的時候的效能比較
效能指標 | 不使用XSendfile | 使用XSendfile |
---|---|---|
耗時 | 1.13s | 456.32ms |
記憶體 | 26.1MB | 2.6MB |