ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LNMP全栈搭建实战:Nginx+PHP-FPM+MySQL动静分离详解

LNMP全栈搭建实战:Nginx+PHP-FPM+MySQL动静分离详解 1. 项目概述为什么一个“LNMP完整搭建”值得专门写三篇实战笔记我做Web服务部署和运维快十二年了从最早在CentOS 5上手编译PHP 5.2到今天用Ansible批量管理上千台容器化节点踩过的坑摞起来能当服务器机柜垫脚石。但每次带新人或者自己重装测试环境LNMP这套组合依然是绕不开的起点——不是因为它多先进而是它像一把瑞士军刀小、稳、透明、可拆解。你摸清了它再往上走Docker、K8s、Service Mesh心里才有底。标题里这个“Nginx系列实战三”不是随便排的序号。前两篇分别讲了Nginx核心配置逻辑location匹配优先级、rewrite执行顺序、变量作用域和反向代理与负载均衡实操健康检查超时设置、upstream动态权重、proxy_buffer调优。而这一篇是真正把Nginx从“单点代理”拉进生产级Web服务闭环的关键一跃LNMP全栈打通 动静分离落地。它解决的不是“能不能跑”而是“跑得稳不稳、快不快、查不查得清、扩不扩得动”。你可能已经用过宝塔、AMH这类面板一键部署但面板背后到底发生了什么为什么PHP-FPM进程突然全挂了却查不到日志为什么静态资源明明放在Nginx本地浏览器却总去后端PHP脚本里绕一圈为什么MySQL连接数爆满但show processlist里全是Sleep状态这些都不是玄学全是LNMP链路上每个环节的配置细节、资源边界和协作逻辑决定的。这篇内容的核心关键词——Nginx、LNMP、动静分离、PHP-FPM、MySQL——每一个都不是孤立存在。Nginx不是只配个server块就完事PHP-FPM不是开个服务就能接请求MySQL更不是装完设个root密码就高枕无忧。它们之间靠FastCGI协议握手、Unix Socket文件权限、TCP连接池复用、HTTP头传递规则、日志时间戳对齐这些“看不见的胶水”粘在一起。任何一个环节松动整个链路就会抖动甚至断裂。所以这篇实战我不讲“下载→解压→启动”这种流水线操作。我要带你一层层剥开Nginx怎么把一个URL请求精准路由给PHP-FPM而不是自己处理PHP-FPM的pm.max_children设成32还是128背后是内存计算还是CPU核数博弈MySQL的wait_timeout和interactive_timeout差10秒为什么会让PHP连接池集体失效动静分离不是简单加个location ~* .(jpg|css|js)$ { try_files $uri 404; }而是要让Nginx真正“接管”静态资源生命周期包括缓存头、ETag生成、Gzip压缩粒度、甚至CDN回源策略预埋。适合谁看刚学完Linux基础命令想亲手搭个WordPress或Typecho博客的开发者已经会用Docker run -d nginx:alpine但搞不清nginx.conf里root和alias区别的人在公司用着云厂商RDSSLB但一遇到慢查询就只会重启数据库的运维同学还有像我这样每年重装三遍测试环境只为验证某个内核参数变更影响的“老折腾人”。接下来的内容全部基于真实生产环境最小可行配置展开。所有命令、路径、参数值我都标注了适用场景和取舍理由。你可以直接抄作业但更建议你边读边问“为什么非得这样”——这才是实战笔记的价值所在。2. 整体架构设计与方案选型为什么坚持手动编译而非Docker或一键脚本很多人看到“LNMP完整搭建”第一反应是“现在谁还手装Docker compose.yml三行搞定。”这话没错但错在混淆了“部署效率”和“系统认知”。就像学开车你可以直接坐进特斯拉按Autopilot但真要修车、调校、应对突发故障必须懂离合器咬合点、变速箱油温阈值、ABS介入逻辑。LNMP同理——Docker封装的是结果手动搭建暴露的是过程。我坚持用源码编译systemd托管独立配置目录的方式原因很实在2.1 版本可控性避免“黑盒依赖”带来的连锁故障去年帮一家做教育SaaS的客户排查502错误他们用某宝塔面板安装的LNMPPHP版本是7.4.33Nginx是1.20.2MySQL是5.7.36。表面看都是稳定版但问题出在PHP-FPM的opcache配置里一个不起眼的参数opcache.validate_timestamps0。这个参数在PHP 7.4.30之后被默认关闭但面板没同步更新模板导致代码更新后页面不刷新。更麻烦的是他们根本找不到opcache.ini在哪——因为面板把所有配置文件打散塞进/etc/php/7.4/fpm/conf.d/目录下编号随机没有注释。手动编译则完全不同Nginx源码包解压路径统一为/usr/local/src/nginx-1.24.0编译参数记录在/usr/local/src/nginx-1.24.0/build.shPHP源码放/usr/local/src/php-8.2.12configure命令完整保存MySQL二进制包解压到/usr/local/mysqlmy.cnf明确指向/etc/my.cnf所有服务的systemd unit文件统一放在/etc/systemd/system/命名规范nginx.service、php-fpm.service、mysqld.service。提示不要迷信“最新版”。Nginx 1.25.x已支持QUIC但生产环境我仍主推1.24.x——因为1.24.0是首个正式支持TLSv1.3的长期支持版且社区补丁最全。PHP选8.2.12而非8.3.0因8.2.x在OPcache稳定性上经过大量电商项目验证。MySQL用8.0.33而非8.1.x因8.0.x的InnoDB死锁检测算法更成熟。2.2 资源隔离与故障定位每个服务“看得见、管得住”一键脚本常把Nginx、PHP、MySQL全塞进同一个systemd scope或Docker网络看似省事实则埋雷。比如PHP-FPM子进程崩溃systemd可能只报php-fpm.service: main process exited, codekilled, status9/KILL但你根本不知道是OOM killer干的还是PHP脚本死循环触发了pm.max_requests限制。手动部署则强制分权Nginx主进程以www-data用户运行worker进程降权为nginx用户PHP-FPM master进程用root但pool进程严格限定为www-data且listen.owner和listen.group设为nginxMySQL以mysql用户运行数据目录/usr/local/mysql/data权限为750属主mysql:mysql所有日志路径独立Nginx日志在/var/log/nginx/PHP-FPM慢日志在/var/log/php-fpm.slow.logMySQL错误日志在/usr/local/mysql/data/error.log。这种隔离带来两个直接好处ps aux | grep nginx能看到精确的master/worker进程树strace -p $(pgrep -f php-fpm: pool www)能实时跟踪PHP进程系统调用journalctl -u php-fpm.service -n 100 --no-pager输出里每条日志都带精确时间戳和进程ID配合/var/log/php-fpm.slow.log里的script_name字段5分钟内定位到慢脚本。2.3 动静分离的底层支撑只有手动才能精细控制“谁该处理什么”所谓动静分离本质是让Nginx承担它最擅长的事——高效分发静态文件把动态请求交给PHP-FPM。但很多教程只教一句location ~* \.(jpg|png|css|js)$ { expires 1y; }这远远不够。真正的动静分离需要三层协同Nginx层通过try_files指令实现“先找静态文件找不到再转给PHP”避免无谓的FastCGI转发PHP-FPM层通过security.limit_extensions限制可执行文件后缀防止.jpg.php类绕过文件系统层静态资源目录如/var/www/static/和动态代码目录如/var/www/app/物理隔离Nginx root指向/var/www但PHP-FPM的doc_root只认/var/www/app/。Docker镜像很难做到这种细粒度控制。比如官方php:8.2-apache镜像Apache和PHP混在一起你想单独调优PHP-FPM的pm模式就得重写Dockerfile。而手动部署/etc/php/8.2/fpm/pool.d/www.conf里一行pm dynamic就能切换模式改完systemctl reload php-fpm立即生效。2.4 安全基线的刚性约束拒绝“默认即危险”的惯性思维所有一键脚本默认开启的选项往往是最不安全的。比如MySQL安装后默认允许root%远程登录PHP默认开启display_errorsOn把SQL错误原样吐给浏览器Nginx默认启用server_tokens on暴露版本号。手动部署时我在每个环节都植入安全卡点MySQL初始化时mysqld --initialize --usermysql生成随机root密码强制首次登录改密PHP配置中expose_php Off、cgi.fix_pathinfo 0、disable_functions exec,passthru,shell_exec,system,proc_open,popenNginx配置里server_tokens off、add_header X-Content-Type-Options nosniff、add_header X-Frame-Options DENY。这些不是锦上添花而是生产环境的生存底线。去年有个客户被挖矿木马入侵根源就是宝塔面板后台的PHP探针未关闭攻击者通过phpinfo()页面获取了/etc/passwd路径再利用PHP的glob()函数遍历到了MySQL配置文件。3. 核心组件安装与配置详解从源码到服务的每一步意图LNMP不是四个字母的拼写而是四段精密咬合的齿轮。下面我按实际操作顺序把每个组件的安装、配置、验证拆解到原子级并说明每个参数背后的“为什么”。3.1 Nginx不只是Web服务器更是流量调度中枢Nginx在这里的角色远超HTTP服务——它是整个链路的入口守门员、静态资源分发器、动态请求路由器。安装必须从源码开始因为二进制包往往缺少关键模块如--with-http_realip_module用于获取真实IP。步骤1准备编译环境与依赖# CentOS 7/8/9通用 yum groupinstall Development Tools -y yum install pcre-devel openssl-devel zlib-devel geoip-devel -y # 注意不要装yum源里的nginx版本老旧且模块缺失实操心得pcre-devel是正则引擎基础openssl-devel支持HTTPSzlib-devel启用Gzip。geoip-devel虽非必需但后续做地域限流时能直接用geoip_country变量比用Lua解析IP库快10倍。步骤2下载并解压源码cd /usr/local/src wget https://nginx.org/download/nginx-1.24.0.tar.gz tar -zxvf nginx-1.24.0.tar.gz cd nginx-1.24.0步骤3configure参数设计——每个开关都是业务需求映射./configure \ --prefix/usr/local/nginx \ --sbin-path/usr/local/nginx/sbin/nginx \ --conf-path/etc/nginx/nginx.conf \ --pid-path/var/run/nginx.pid \ --lock-path/var/run/nginx.lock \ --error-log-path/var/log/nginx/error.log \ --http-log-path/var/log/nginx/access.log \ --with-http_ssl_module \ --with-http_v2_module \ --with-http_realip_module \ --with-http_stub_status_module \ --with-http_gzip_static_module \ --with-file-aio \ --with-threads \ --with-stream \ --with-stream_ssl_module \ --with-stream_realip_module关键参数解读--with-http_v2_module必须开启HTTP/2现代浏览器默认走h2能显著减少TCP连接数--with-http_realip_module当Nginx前有CDN或负载均衡时用set_real_ip_from和real_ip_header X-Forwarded-For还原真实客户端IP--with-http_gzip_static_module让Nginx直接返回预压缩的.gz文件需提前用gzip命令生成比运行时压缩CPU开销低80%--with-stream开启TCP/UDP四层代理能力后续可代理MySQL、Redis等非HTTP服务。步骤4编译安装与systemd服务注册make make install # 创建systemd服务文件 cat /etc/systemd/system/nginx.service EOF [Unit] Descriptionnginx - high performance web server Documentationhttp://nginx.org/en/docs/ Afternetwork-online.target remote-fs.target nss-lookup.target Wantsnetwork-online.target [Service] Typeforking PIDFile/var/run/nginx.pid ExecStartPre/usr/local/nginx/sbin/nginx -t -c /etc/nginx/nginx.conf ExecStart/usr/local/nginx/sbin/nginx -c /etc/nginx/nginx.conf ExecReload/bin/kill -s HUP $MAINPID ExecStop/bin/kill -s TERM $MAINPID PrivateDevicestrue ProtectSystemfull ProtectHometrue NoNewPrivilegestrue [Install] WantedBymulti-user.target EOF systemctl daemon-reload systemctl enable nginx systemctl start nginx注意ExecStartPre里的-t参数是语法检查避免配置错误导致服务启动失败ProtectSystemfull禁止Nginx修改/usr、/boot等关键目录这是容器外的安全加固。3.2 MySQL数据底座的稳定性比功能更重要MySQL 8.0.x是分水岭版本InnoDB集群、角色管理、JSON增强都很炫但生产环境我首选8.0.33 LTS版——它的Redo Log刷盘策略和Buffer Pool预热机制最成熟。步骤1创建用户与目录groupadd mysql useradd -r -g mysql -s /bin/false mysql mkdir -p /usr/local/mysql mkdir -p /usr/local/mysql/data chown -R mysql:mysql /usr/local/mysql步骤2下载二进制包并初始化cd /usr/local/src wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.33-linux-glibc2.12-x86_64.tar.xz tar -xf mysql-8.0.33-linux-glibc2.12-x86_64.tar.xz mv mysql-8.0.33-linux-glibc2.12-x86_64 /usr/local/mysql # 初始化关键 /usr/local/mysql/bin/mysqld --initialize --usermysql --datadir/usr/local/mysql/data --basedir/usr/local/mysql # 记录生成的临时root密码在error.log末尾步骤3编写my.cnf——性能与安全的平衡点[mysqld] # 基础路径 basedir /usr/local/mysql datadir /usr/local/mysql/data socket /tmp/mysql.sock pid-file /var/run/mysqld/mysqld.pid # 网络与安全 bind-address 127.0.0.1 port 3306 skip-networking OFF max_connections 200 wait_timeout 28800 interactive_timeout 28800 # 关键禁用符号链接防止任意文件读取 secure_file_priv /var/lib/mysql-files/ sql_mode STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION # InnoDB优化 innodb_buffer_pool_size 1G innodb_log_file_size 256M innodb_flush_log_at_trx_commit 1 innodb_flush_method O_DIRECT innodb_io_capacity 200 innodb_io_capacity_max 2000 # 日志 log-error /usr/local/mysql/data/error.log slow_query_log ON slow_query_log_file /usr/local/mysql/data/slow.log long_query_time 2参数深挖wait_timeout 288008小时PHP-FPM的mysql.connect_timeout默认30秒但连接池复用时空闲连接存活时间必须大于PHP的max_execution_time通常30-60秒否则会出现MySQL server has gone awayinnodb_buffer_pool_size 1G设为物理内存的50%-75%但绝不超过free -h显示的可用内存否则触发OOMinnodb_flush_log_at_trx_commit 1牺牲一点性能保数据安全生产环境绝不妥协。步骤4systemd服务与安全加固cat /etc/systemd/system/mysqld.service EOF [Unit] DescriptionMySQL Server Documentationman:mysqld(8) Afternetwork.target [Service] Typesimple Usermysql Groupmysql ExecStart/usr/local/mysql/bin/mysqld --defaults-file/etc/my.cnf Restarton-failure RestartSec10 LimitNOFILE 65535 [Install] WantedBymulti-user.target EOF systemctl daemon-reload systemctl enable mysqld systemctl start mysqld初始化后必须执行的安全操作# 登录并改密用初始化日志里的临时密码 /usr/local/mysql/bin/mysql -u root -p ALTER USER rootlocalhost IDENTIFIED BY YourStrongPass123!; # 创建应用专用用户绝不直接用root CREATE USER appuserlocalhost IDENTIFIED BY AppPass456!; GRANT SELECT,INSERT,UPDATE,DELETE ON appdb.* TO appuserlocalhost; FLUSH PRIVILEGES;3.3 PHP-FPM动态请求的执行引擎与资源守门人PHP 8.2是当前最佳平衡点JIT编译器对CPU密集型任务提升明显而OPcache的validate_timestamps和revalidate_freq参数组合能兼顾开发调试与生产性能。步骤1安装依赖与解压源码yum install libxml2-devel openssl-devel bzip2-devel libcurl-devel libjpeg-devel libpng-devel freetype-devel gmp-devel sqlite-devel oniguruma-devel -y cd /usr/local/src wget https://windows.php.net/downloads/releases/php-8.2.12.tar.gz tar -zxvf php-8.2.12.tar.gz cd php-8.2.12步骤2configure参数——聚焦LNMP协同需求./configure \ --prefix/usr/local/php \ --with-config-file-path/etc/php/8.2/cli \ --with-config-file-scan-dir/etc/php/8.2/cli/conf.d \ --enable-fpm \ --with-fpm-userwww-data \ --with-fpm-groupwww-data \ --with-fpm-systemd \ --enable-opcache \ --with-mysqlnd \ --with-pdo-mysqlmysqlnd \ --with-openssl \ --with-curl \ --with-gd \ --with-jpeg-dir \ --with-png-dir \ --with-freetype-dir \ --enable-mbstring \ --enable-xml \ --enable-bcmath \ --enable-zip \ --with-zlib \ --enable-soap \ --enable-intl \ --with-ldap \ --without-pear关键点--with-fpm-systemd让PHP-FPM原生支持systemdsystemctl status php-fpm能显示精确进程状态--with-mysqlnd使用MySQL原生驱动比--with-mysql更稳定且支持mysqli_options(MYSQLI_OPT_CONNECT_TIMEOUT)--enable-opcache必须开启但后续要在php.ini里精细调优。步骤3编译安装与FPM配置make make install # 创建配置目录 mkdir -p /etc/php/8.2/{cli,fpm} cp php.ini-production /etc/php/8.2/cli/php.ini cp /usr/local/php/etc/php-fpm.conf.default /etc/php/8.2/fpm/php-fpm.conf cp /usr/local/php/etc/php-fpm.d/www.conf.default /etc/php/8.2/fpm/pool.d/www.conf/etc/php/8.2/fpm/pool.d/www.conf核心调优[www] user www-data group www-data listen /run/php/php-fpm.sock listen.owner nginx listen.group nginx listen.mode 0660 pm dynamic pm.max_children 32 pm.start_servers 10 pm.min_spare_servers 5 pm.max_spare_servers 15 pm.max_requests 1000 slowlog /var/log/php-fpm.slow.log request_slowlog_timeout 5s catch_workers_output yes计算逻辑pm.max_children 32按每个PHP进程平均占用40MB内存估算32×40MB≈1.28GB留出余量给系统和其他服务pm.max_requests 1000防止内存泄漏累积每处理1000个请求后自动重启workerlisten.mode 0660确保Nginx属于nginx组能读写sock文件但其他用户不可访问。步骤4systemd服务与启动cat /etc/systemd/system/php-fpm.service EOF [Unit] DescriptionThe PHP FastCGI Process Manager Afternetwork.target [Service] Typenotify Userroot Groupwww-data ExecStart/usr/local/php/sbin/php-fpm --nodaemonize --fpm-config /etc/php/8.2/fpm/php-fpm.conf Restarton-failure RestartSec10 PrivateDevicestrue ProtectSystemfull ProtectHometrue [Install] WantedBymulti-user.target EOF systemctl daemon-reload systemctl enable php-fpm systemctl start php-fpm3.4 动静分离的Nginx配置让静态资源“飞起来”动态请求“稳下来”这才是本篇的灵魂。很多教程把动静分离写成“加个location正则”但真正的分离是请求生命周期的重新定义。标准LNMP站点结构约定/var/www/example.com/ ├── html/ # 动态PHP代码index.php等 ├── static/ # 静态资源css/js/img/fonts └── logs/ # 站点专属日志核心nginx.conf片段/etc/nginx/conf.d/example.com.confserver { listen 80; server_name example.com; root /var/www/example.com/html; index index.php index.html; # 静态资源精准匹配最高优先级 location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|eot|svg)$ { root /var/www/example.com/static; expires 1y; add_header Cache-Control public, immutable; add_header Last-Modified ; add_header ETag ; # 关键禁用PHP解析 location ~ \.php$ { deny all; } } # PHP动态请求仅处理html目录下的.php location ~ \.php$ { # 先验证文件是否存在避免Nginx将不存在的.php转给PHP-FPM造成502 try_files $uri 404; fastcgi_pass unix:/run/php/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; # 传递真实客户端IP当有前置代理时 fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param HTTP_X_REAL_IP $http_x_real_ip; } # 防止敏感文件被直接访问 location ~ /\. { deny all; } location ~ /(config|vendor|node_modules|\.git) { deny all; } }配置意图逐行解析location ~* \.(jpg|...)$~*表示不区分大小写正则匹配root /var/www/example.com/static让Nginx直接从static目录读取不经过PHPexpires 1y设置1年缓存浏览器不再发起请求add_header Cache-Control public, immutableimmutable告诉浏览器此资源永不过期即使用户按F5也不重载try_files $uri 404这是动静分离的保险栓。如果请求/test.php但文件不存在Nginx直接返回404绝不转发给PHP-FPM避免无谓的进程创建fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name$document_root是/var/www/example.com/html确保PHP只执行html目录下的脚本static目录里的.php文件永远无法被执行。实操心得曾有个客户网站被注入恶意JS攻击者上传了/static/bad.php。由于旧配置没加location ~ \.php$ { deny all; }嵌套这个文件被Nginx当作静态资源返回但浏览器执行时又触发了PHP解析——双重漏洞。新配置用嵌套location彻底堵死。4. 全链路连通性验证与性能调优从“能跑”到“跑好”的临门一脚装完只是开始验证才是关键。我有一套标准化的五步验证法覆盖连通性、功能性、安全性、性能、可观测性。4.1 Step 1基础连通性验证5分钟目标确认四个服务各自正常且能互相通信。Nginx验证curl -I http://127.0.0.1 # 应返回 HTTP/1.1 200 OK 和 Server: nginx 头 # 检查监听端口 ss -tlnp | grep :80 # 应看到 nginx 进程MySQL验证mysql -uappuser -pAppPass456! -h127.0.0.1 -e SELECT VERSION(); # 应返回 MySQL 8.0.33 版本号 # 检查连接数 mysql -uroot -pYourStrongPass123! -e SHOW STATUS LIKE Threads_connected;PHP-FPM验证# 检查sock文件权限 ls -l /run/php/php-fpm.sock # 应显示 srw-rw---- 1 root nginx且nginx组可读写 # 测试FastCGI响应 SCRIPT_NAME/index.php SCRIPT_FILENAME/var/www/example.com/html/index.php REQUEST_METHODGET cgi-fcgi -bind -connect /run/php/php-fpm.sock # 应返回 PHP 输出可能为空但无错误动静分离初验# 创建测试文件 echo ?php echo PHP OK; ? /var/www/example.com/html/test.php echo STATIC OK /var/www/example.com/static/test.txt # 请求动态 curl http://127.0.0.1/test.php # 应返回 PHP OK # 请求静态 curl http://127.0.0.1/test.txt # 应返回 STATIC OK # 关键请求静态目录下的php应404 curl http://127.0.0.1/test.php # 注意路径是根目录应404因root指向html curl http://127.0.0.1/static/test.php # 应404因嵌套deny规则4.2 Step 2功能完整性验证10分钟目标模拟真实业务场景验证全链路数据流转。创建WordPress最小化测试cd /var/www/example.com/html wget https://wordpress.org/latest.tar.gz tar -zxvf latest.tar.gz --strip-components1 # 修改wp-config.php sed -i s/DB_NAME, database_name_here/DB_NAME, wp_test/g wp-config.php sed -i s/DB_USER, username_here/DB_USER, appuser/g wp-config.php sed -i s/DB_PASSWORD, password_here/DB_PASSWORD, AppPass456!/g wp-config.php sed -i s/DB_HOST, localhost/DB_HOST, 127.0.0.1/g wp-config.php # 创建数据库 mysql -uroot -pYourStrongPass123! -e CREATE DATABASE wp_test CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;访问安装向导浏览器打开http://your-server-ip/wp-admin/install.php应看到WordPress安装界面。填写信息后点击“安装”成功后出现“成功”提示页。注意此时观察Nginx access.log应看到大量/wp-admin/*.php请求状态码200同时/wp-content/themes/twentytwentythree/style.css等静态请求状态码200且Cache-Control头为public, immutable。4.3 Step 3安全性深度扫描15分钟目标主动暴露风险点而非等待被攻破。工具链nikto -h http://127.0.0.1扫描Web服务器配置弱点如目录遍历、危险HTTP方法mysql -uroot -p -e SELECT user,host,plugin FROM mysql.user;检查是否有%通配符用户php -m | grep -E (pdo|mysql|opcache)确认关键扩展已加载nginx -t语法检查避免reload时中断服务。关键检查项检查点命令合格标准Nginx版本隐藏curl -I http://127.0.0.1 | grep Server返回Server: nginx无版本号PHP错误关闭curl http://127.0.0.1/test.php?abc123不返回PHP警告只返回空白或自定义错误页MySQL远程禁用mysql -uappuser -p -h 公网IP -e SELECT 1;连接拒绝因bind-address127.0.0.1静态资源PHP执行curl http://127.0.0.1/static/test.php返回404或403绝不返回PHP输出4.4 Step 4性能基准测试20分钟目标量化动静分离效果建立性能基线。工具abApache Bench# 测试静态资源100并发1000次请求 ab -n 1000 -c 100 http://127.0.0.1/static/style.css # 测试动态PHP同样参数 ab -n 1000 -c 100 http://127.0.0.1/test.php典型结果对比4核8G服务器请求类型Requests per secondTime per request (ms)Failed requests静态CSS12,8407.790动态PHP1,24080.650差距10倍印证了动静分离的价值。但更要关注动态请求的稳定性Time per request标准差应10ms过大说明PHP-FPM进程抖动Failed requests为0否则检查pm.max_children是否不足。OPcache命中率监控创建/var/www/example.com/html/opcache.php?php if (function_exists(opcache_get_status)) { $status opcache_get_status(); echo Hit rate: . round($status[opcache_statistics][hit_rate], 2) . %\n; echo Memory used: . round($status[memory_usage][used_memory]/1024/1024, 2) . MB\n; echo Cached scripts: . $status[opcache_statistics][num_cached_scripts] . \n; } ?访问http://127.0.0.1/opcache.php理想状态Hit rate 95%说明代码缓存高效Memory used 80% ofopcache.memory_consumption默认128MBCached scripts 100WordPress核心约200文件。4.5 Step 5可观测性体系搭建30分钟目标让系统“会说话”故障时5分钟内定位。Nginx日志增强在/etc/nginx/nginx.conf的http块中
返回列表