Apache-2.2

呼叫 API 時如何更好地配置 nginx 以減少冗餘系統呼叫?

  • December 4, 2020

我有一個在生產環境中執行的 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來實現。

引用自:https://serverfault.com/questions/1044929