呼叫 API 時如何更好地配置 nginx 以減少冗餘系統呼叫?
我有一個在生產環境中執行的 Laravel 應用程序,並且有一些 API 使用很多。某些東西造成了瓶頸,它曾經使我們的伺服器停止執行(3 個帶有負載均衡器)。在優化了 Laravel 的基礎,記憶體配置、路由、數據等,甚至解決了所有 n+1 問題後,我們仍然在高峰期遇到問題。有人建議我們在其中一個 nginx 工作人員上執行 strace 以查看系統級別發生了什麼,所以我們這樣做了,而且很有趣,有很多冗餘系統呼叫,當呼叫 API 時 nginx 會嘗試查找文件:
部分跟踪:
240498 stat("/var/www/html/myProject/current/public/APIRequest/3d4f7518e04e9", 0x7ffc7ee6ff70) = -1 ENOENT (No such file or directory) 240498 stat("/var/www/html/myProject/current/public/APIRequest/3d4f7518e04e9", 0x7ffc7ee6ff70) = -1 ENOENT (No such file or directory) 240498 lstat("/var", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 240498 lstat("/var/www", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 240498 lstat("/var/www/html", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 240498 lstat("/var/www/html/myProject", {st_mode=S_IFDIR|0777, st_size=4096, ...}) = 0 240498 lstat("/var/www/html/myProject/current", {st_mode=S_IFLNK|0777, st_size=48, ...}) = 0 240498 readlink("/var/www/html/myProject/current", "/var/www/html/myProject/release"..., 4095) = 48 240498 lstat("/var", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 240498 lstat("/var/www", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 240498 lstat("/var/www/html", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 240498 lstat("/var/www/html/myProject", {st_mode=S_IFDIR|0777, st_size=4096, ...}) = 0 240498 lstat("/var/www/html/myProject/releases", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0 240498 lstat("/var/www/html/myProject/releases/20201202085755", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0 240498 lstat("/var/www/html/myProject/releases/20201202085755/public", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
現在,在這種情況下使用 ID 呼叫 API
3d4f7518e04e9
,並嘗試遍歷目錄以查找該文件。但它不是一個文件,它是一個 API。我們執行 strace 的時間不到 30 秒,我們有 5k 次這樣的呼叫,這對我來說沒有意義。那麼,這些呼叫是否必要?我不這麼認為,但如果我錯了,請告訴我。如果我是對的,我怎樣才能更好地配置我的 nginx,以便這些呼叫可以“及時擷取”並得到適當的解決。歡迎任何想法。:)
PS:我們也嘗試過具有類似配置的 apache,在 strace 中出現了同樣的問題。
編輯:我是否只需要在我的站點配置中添加某種位置指令來解決這個問題?我正在使用官方文件https://laravel.com/docs/8.x/deployment#nginx中的基本 nginx conf,並添加了更多內容,例如:
location ~ \.php$ { fastcgi_pass unix:/var/run/php/php7.2-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; include fastcgi_params; fastcgi_buffer_size 128k; fastcgi_buffers 256 16k; fastcgi_busy_buffers_size 256k; fastcgi_temp_file_write_size 256k; } location ~ /\.(?!well-known).* { deny all; } client_body_buffer_size 10K; client_header_buffer_size 1k; client_max_body_size 8m; large_client_header_buffers 4 16k; client_body_timeout 12; client_header_timeout 12; keepalive_timeout 15; send_timeout 10;
編輯:
location / { try_files $uri $uri/ /index.php?$query_string; }
我確實按照 Danila Vershinin 在回答中的建議嘗試了文件
看起來您正在處理
try_files
性能問題。您可以通過從配置中刪除來擺脫不必要的stat
系統呼叫。try_files
該
try_files
指令為創建對 SEO 友好的網站提供了一個漂亮而簡單的樣板。然而,這種簡單性的缺點是增加了不必要的
stat
系統呼叫成本。由於您知道,例如所有
/api/
URL 都必須通過您的 PHP 進行路由,因此無需檢查那裡是否存在任何文件,您可以無條件地通過您的 Laravel 引導文件進行路由,例如:location /api/ { fastcgi_param SCRIPT_FILENAME $document_root/index.php; include fastcgi_params; fastcgi_pass unix:/var/run/php-fpm/example.com.sock; }
此外,通常,您希望 NGINX 記憶體有關文件/目錄存在的資訊。這可以通過open_file_cache來實現。