Как лучше настроить nginx, чтобы уменьшить избыточные системные вызовы при вызове API?

У меня есть приложение Laravel, работающее в производстве, и есть несколько API-интерфейсов, которые часто используются. Что-то создавало узкое место, и оно раньше тормозило наши серверы (3 с Load Balancer). После оптимизации основ Laravel, кэширования конфигурации, маршрутов, данных и так далее, даже после решения всех проблем n+1, у нас все еще были проблемы в часы пик. Кто-то предложил запустить strace на одном из воркеров nginx, чтобы увидеть, что происходит на системном уровне, что мы и сделали, и, что довольно интересно, существует множество избыточных системных вызовов, когда nginx пытается найти файлы при вызове API:

Часть следа:

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

Теперь API вызывается с идентификатором 3d4f7518e04e9в этом случае и вместо этого он пытается просмотреть каталоги, чтобы найти этот файл. Но это не файл, это API. Мы запускали strace менее 30 секунд, и у нас есть 5k таких вызовов, которые для меня не имеют смысла.

Итак, нужны ли эти звонки? Я так не думаю, но скажите, если я ошибаюсь. И если я прав, как мне лучше настроить мой nginx, чтобы эти вызовы можно было "поймать вовремя" и разрешить соответствующим образом. Любые идеи приветствуются.:)

PS: Мы также пробовали apache с аналогичной конфигурацией, такая же проблема возникает в strace.

Изменить: мне просто нужна какая-то директива местоположения на моем сайте, чтобы решить эту проблему? Я использую базовую конфигурацию nginx из официальных документов https://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;
    }

У меня есть пробные файлы, как предложил Данила Вершинин в ответе

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 о существовании файлов / каталогов. Этого можно добиться с помощью open_file_cache.

Другие вопросы по тегам