如何更好的配置nginx,減少呼叫API時多餘的系統呼叫?

如何更好的配置nginx,減少呼叫API時多餘的系統呼叫?

我有一個在生產環境中運行的 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中出現了同樣的問題。

編輯:我是否只需要在網站配置中添加某種位置指令來解決此問題?我正在使用官方文件中的基本 nginx confhttps://laravel.com/docs/8.x/deployment#nginx還有一些補充,例如:

    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 在答案中建議的文件

答案1

看起來您正在處理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 快取有關檔案/目錄存在的資訊。這可以透過以下方式實現開啟檔案快取

相關內容