프로덕션 환경에서 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
이제 API는 이 경우 ID로 호출되며 3d4f7518e04e9
대신 해당 파일을 찾기 위해 디렉터리를 순환하려고 시도합니다. 하지만 파일이 아니라 API입니다. 우리는 30초도 안 되는 시간 동안 strace를 실행했고, 나에게는 이해가 되지 않는 그러한 호출이 5,000개 있었습니다.
그렇다면 이러한 호출이 필요합니까? 저는 그렇게 생각하지 않습니다. 하지만 제가 틀렸다면 말씀해주세요. 그리고 내가 옳다면 이러한 호출이 "제 시간에 포착"되어 적절하게 해결될 수 있도록 어떻게 nginx를 더 잘 구성할 수 있습니까? 어떤 아이디어라도 환영합니다. :)
추신: 유사한 구성으로 Apache를 시도했지만 strace에서도 동일한 문제가 나타납니다.
편집: 이 문제를 해결하려면 내 사이트 구성에 일종의 위치 지시문이 필요합니까? 공식 문서의 기본 nginx conf를 사용하고 있습니다.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;
}
답변에서 Danila Vershinin이 제안한 시험 파일이 있습니다.
답변1
try_files
성능 문제를 다루고 있는 것 같습니다 . 불필요한 stat
시스템 호출을 제거할 수 있습니다 .제거하다try_files
귀하의 구성에서.
이 try_files
지시문은 SEO 친화적인 웹사이트를 만들기 위한 훌륭하고 간단한 상용구를 제공합니다.
그러나 이러한 단순성의 단점은 불필요한 stat
시스템 호출로 인해 추가 비용이 발생한다는 것입니다.
예를 들어 모든 URL은 PHP를 통해 라우팅되어야 한다는 것을 알고 있으므로 /api/
거기에 파일이 있는지 확인할 필요가 없으며 무조건 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.