Как лучше настроить 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.