我有一个在生产环境中运行的 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 引导文件进行路由,例如:此外,通常,您希望 NGINX 缓存有关文件/目录存在的信息。这可以通过open_file_cache来实现。