新闻详情

新闻详情

首页 / 资讯中心 / 详情

LNMP动静分离实践:Nginx与PHP-FPM协同配置全解析

发布时间:2026/9/14 18:37:28来源:尧图网络
LNMP动静分离实践:Nginx与PHP-FPM协同配置全解析
动静分离这四个字很多教程里写得轻飘飘好像就是在Nginx里加一段location规则那么简单。但真正自己从头搭一套LNMP环境把Nginx、PHP-FPM、MySQL三层理顺再让动静请求各走各的路你会发现真正的坑根本不在“加一段规则”而在于你压根没搞清楚Nginx在整个体系里到底应该承揽多少活、甩出去多少活。这篇我把自己在LNMP搭建和动静分离上的完整实践过程整理出来从组件选型到配置文件骨架再到线上最容易翻车的几个问题排查该走的弯路都替你走一遍适合正在搭LNMP、或者Nginx里一堆location但不知道什么时候该用哪一种的读者。1. 动静分离前先把Nginx的工作模式看通透Nginx在整个LNMP里的角色很多人上来就误解了。它不是代替PHP解析动态脚本也不是替你扛数据库压力它做的事情本质上只有三类静态文件的高速分发、HTTP请求的反向代理、连接与协议的调度管理。1.1 Nginx不是“Web服务器”那么简单传统认为Web服务器负责整个HTTP请求周期但这在Nginx的模型里是不准确的。Nginx对静态文件的处理确实非常快因为这属于它的核心强项——基于事件驱动架构一个worker进程可以同时处理海量连接不依赖线程池。但对于PHP、Python这类动态语言Nginx本身是不会“解析”的它只负责把符合条件的请求转交给外部的FastCGI进程管理器PHP-FPM等PHP-FPM把脚本跑完、生成标准的HTTP响应Nginx再把这个响应原样返回给客户端。所以看一张典型的LNMP请求链路就清楚了客户端请求 ↓ Nginx 监听 80/443 端口 ├── 静态资源(.js/.css/.jpg/.png) → Nginx直接读磁盘返回 ├── 动态请求(.php 或特定URL) → 转发给 PHP-FPM(fastcgi_pass) └── 非后端请求(其他静态/重定向) → 按规则处理 ↓ PHP-FPM 解析PHP脚本 ↓ PHP 通过 MySQLi/PDO 访问 MySQL ↓ MySQL 返回数据 → PHP 生成HTML/JSON → PHP-FPM → Nginx → 客户端Nginx在这里更像一个前厅领位员PHP-FPM是后厨MySQL是仓库。领位员只负责把“需要后厨处理的客单”递给后厨把“直接拿现成小吃就能走的客单”现场交付而不是自己钻进后厨去炒菜。1.2 动静分离为什么能提升并发没有动静分离时如果让Nginx把所有文件——包括图片、CSS、JS——都转给PHP-FPM处理那PHP-FPM就要反复解析PHP进程、连接MySQL、动态读取文件并返回二进制内容。这个过程不是不能工作而是会让性能崩得非常快。PHP-FPM默认的pm.max_children数量有限静态文件的高频请求很快就会把PHP进程池占满真正需要PHP处理的业务动态请求反而排队这就是很多站点突发访问量上来后白屏、超时的直接原因。动静分离之后静态资源由Nginx直接从磁盘、内存缓存甚至CDN就近返回完全不走PHP和MySQL动态请求才进入PHP-FPM。分离之后你会发现同一台配置的机器能抗住的并发量可能提升一个数量级。Nginx官方资料里常说“静态文件处理能力达到数万并发”这里的数字就是在不经过PHP-FPM的前提下测出来的。所以理解了这一层之后再动手去改配置思路就完全不一样了。2. LNMP组件选型与平台兼容性很多LNMP教程上来就yum install nginx php-fpm mysql-server好像所有Linux发行版的软件源里都齐刷刷躺着这些包。但实际生产遇到的情况要复杂得多尤其是国产化环境、ARM架构、离线内网环境这三个场景我全部踩过。2.1 一套经过验证的版本组合先给出一套我在实际环境里跑稳过的组合不一定追最新但抗造、资料多、互相之间没有兼容性坑组件版本选择用途与说明Nginx1.24.x或发行版自带1.20核心Web服务器与反向代理PHP8.1.x支持到2024年底长期维护FastCGI后端配PHP-FPMMySQL8.0.xPercona或官方社区版数据存储账号隔离这个组合的前提是你能联网yum/apt源里有对应包。但现实往往不按剧本来。2.2 离线环境与ARM架构的处理有段时间需要在麒麟V11上装LNMP而且还是内网离线环境yum源根本连不通也没有现成的rpm包。当时我做的事简单说就是找一台能联网的、同架构同操作系统的机器用yumdownloader把需要的rpm连依赖全部拉下来再拷进内网装。用到的核心命令大致是这样# 在联网机器上安装 yum-utils yum install -y yum-utils # 只下载不安装把指定包及其依赖全部拉到本地目录 mkdir -p /data/rpms yumdownloader --destdir/data/rpms --resolve nginx php-fpm php-common php-mysqlnd php-json php-gd php-mbstring mysql-server # 打包拷进内网后执行本地安装 cd /data/rpms rpm -Uvh *.rpm这里有一个容易翻车的细节--resolve只能保证yum已知依赖但PHP扩展之间有时存在隐式的版本匹配关系比如php-fpm和php-common的版本必须完全一致否则rpm会报“conflicts”或“requires”错误。我的习惯是敲完命令后在目标机器上先跑php -v确认版本再单独验证php-fpm -t配置语法。至于ARM架构aarch64移植关键不是把x86的包硬拷过去而是直接在ARM机器上编译安装。编译Nginx之前确认三件事pcre-devel、zlib-devel、openssl-devel这三个依赖库是否就位同时如果机器内存小于2G编译时建议加--with-cc-opt-O1避免内存溢出最后别忘加--with-stream很多后来的TCP/UDP四层代理需求都会用到它编进去了后面省得再折腾。2.3 Docker和裸机部署怎么选热搜词里出现很多docker pull nginx、docker部署nginx的搜索说明容器化部署已经是大趋势。Docker部署LNMP确实省事一条docker compose up -d就能把三个容器拉起来但前提是你能接受三个现实问题一是镜像仓库在内外网之间的访问限制内网环境得自建Harbor或导入镜像tar包二是数据落盘问题MySQL容器一旦被删除数据卷如果没做好备份数据直接蒸发三是性能瓶颈Docker网络NAT转发在高并发短连接场景下确实比宿主机直接跑要损失一些性能。我的判断标准很简单开发环境、团队协作环境直接用Docker Compose最香生产环境如果是单机或双机规模不大裸机部署反而更好排查问题。如果你已经有K8s那一套运维体系那又另当别论。这篇文章以裸机部署为主线因为动静分离的本质逻辑在容器里也是一模一样的换汤不换药。3. LNMP各层协作的配置骨架整套LNMP的配置不需要一次到位我的做法是先把每个组件单独跑通再谈配合。PHP-FPM先能处理一个简单的?php phpinfo(); ?文件MySQL先能建库建账号Nginx最后把两者串起来。这样的排查路径最短。3.1 PHP-FPM的独立配置安装完成后PHP-FPM的配置文件一般在/etc/php-fpm.d/www.confCentOS系或/etc/php/8.1/fpm/pool.d/www.confDebian系。最关键的是几个参数; 运行用户和用户组 user nginx group nginx ; 监听方式优先选Unix Socket而不是TCP端口 listen /run/php-fpm/www.sock listen.owner nginx listen.group nginx listen.mode 0660 ; 进程管理方式 pm dynamic pm.max_children 50 pm.start_servers 5 pm.min_spare_servers 5 pm.max_spare_servers 35 pm.max_requests 500这里值得解释的是listen为什么优先用Unix Socket。Socket走的是内核进程间通信不经过TCP/IP协议栈没有端口监听和三次握手开销在同一台机器上转发的性能明显优于127.0.0.1:9000这种TCP方式。代价就是Socket文件有权限问题Nginx的工作进程user nginx必须对该Socket文件有读写权限否则就会遇到经典的502 Bad Gateway。上面配置里的listen.owner nginx就是专门解决这一步权限控制的。pm dynamic是生产环境最常见的选择平时预留几个空闲进程高峰时动态扩展到上限避免突发流量把进程全部占满后产生502。pm.max_requests防止单个进程无限持有循环引用导致的内存泄漏每处理500个请求后就自动重启这个worker进程这是一种很朴素的“自我修复”机制。3.2 Nginx主配置的结构化拆分没有哪个正经的项目会把所有配置堆在nginx.conf一个文件里。正确做法是让主配置只干三件事定义全局事件模型、加载http模块、include站点配置。我习惯的项目目录结构/etc/nginx/ ├── nginx.conf ├── conf.d/ │ ├── default.conf │ └── project.conf └── ssl/ └── yourdomain.com/ ├── fullchain.pem └── privkey.pemnginx.conf里需要修改的核心参数不多但每一条都有讲究user nginx; worker_processes auto; # 自动匹配CPU核心数 worker_rlimit_nofile 65535; # 单进程最大文件句柄数高并发时必须提 events { use epoll; # Linux下高性能事件模型 worker_connections 10240; # 单worker可承载的连接数 } http { include mime.types; default_type application/octet-stream; sendfile on; tcp_nopush on; keepalive_timeout 65; gzip on; include /etc/nginx/conf.d/*.conf; }worker_rlimit_nofile这一行很多教程根本不会提到。默认情况下进程能打开的文件句柄上限是1024这对静态文件服务器来说根本不够。如果连接数上来了你会发现Nginx错误日志里全是“Too many open files”这就是文件句柄不足导致的。要么在nginx.conf里加这一行要么改/etc/security/limits.conf二选一但要记得改完都需要重载或重启进程才会生效。3.3 MySQL只做该做的事MySQL这边需要明确一个原则不要在生产环境给PHP应用用root账号连接数据库。我曾经见过一个项目php脚本用root连接MySQL后来被SQL注入拖走了整库数据教训太惨了。规范的流程是这样-- 创建独立数据库 CREATE DATABASE IF NOT EXISTS app_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 创建专用账号只授予应用需要的权限 CREATE USER app_user127.0.0.1 IDENTIFIED BY StrongPassword123!; CREATE USER app_userlocalhost IDENTIFIED BY StrongPassword123!; -- 只给这个库授权不给全局权限 GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX ON app_db.* TO app_user127.0.0.1; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX ON app_db.* TO app_userlocalhost; FLUSH PRIVILEGES;注意我同时创建了127.0.0.1和localhost两个账号因为PHP的mysqli/PDO如果用IP去连走的是TCP认证用localhost走的是Socket认证你如果不建两个账号总有一种连接方式会报Access denied。这个细节卡过很多人。PHP脚本里去连数据库的示例?php $pdo new PDO( mysql:host127.0.0.1;dbnameapp_db;charsetutf8mb4, app_user, StrongPassword123!, [ PDO::ATTR_ERRMODE PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE PDO::FETCH_ASSOC, ] );等这三个组件各自跑通了再进下一步做动静分离的整合。4. 动静分离的核心location匹配优先级与路径设计终于到了这篇文章的主角。动静分离的配置集中在Nginx的server块里通过location指令把不同类型的请求分到不同的处理路径。但很多人只记住了语法没搞懂匹配优先级写出来的规则经常被Nginx“无视”。4.1 location匹配优先级一条一条拆开讲Nginx的location有四种匹配方式优先级从高到低是精确匹配比如location /favicon.ico只有完全等于这个路径才命中一旦命中立即返回不再往下找。前缀匹配^~比如location ^~ /static/以这个路径开头的URL都会命中且命中后不再做正则匹配。正则匹配~或~*比如location ~ \.php$~*表示不区分大小写。Nginx会按配置文件里的顺序逐个测试正则一旦正则匹配上就停。普通前缀匹配没有和^~修饰的路径比如location /api/、location /先做最长前缀匹配再把匹配结果暂存继续检查有没有正则能命中。平时最容易踩的坑就是正则的优先级高于普通前缀匹配。你以为写了location /api { ... }就能把所有API请求拦住结果在它下面是location ~ \.php$ { ... }某个/api/user.php的请求反而被PHP规则接管了。给一个典型动静分离的完整配置server { listen 80; server_name example.com; # 站点根目录 root /var/www/example.com; index index.php index.html; # 纯静态资源图片、CSS、JS交给Nginx自己处理 location ^~ /static/ { alias /var/www/example.com/static/; expires 30d; access_log off; add_header Cache-Control public, immutable; } # 动态请求所有PHP文件走FastCGI location ~ \.php$ { fastcgi_pass unix:/run/php-fpm/www.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; fastcgi_param HTTPS off; } # 其他所有请求默认交给PHP入口文件 location / { try_files $uri $uri/ /index.php?$query_string; } }这段配置里包含了一个最经典的坑alias和root的区别。4.2 alias和root90%静态资源404都出在这里root和alias在静态资源路径处理上有本质区别root /var/www/example.com加上location /static/实际访问/static/a.png时Nginx会去/var/www/example.com/static/a.png找文件也就是把URI原样拼到root后面。alias /var/www/example.com/static/加上location /static/实际访问/static/a.png时Nginx会把location里匹配到的前缀去掉再把剩余路径拼到alias后面也就是去/var/www/example.com/static/a.png找。看上面这个配置如果你把alias /var/www/example.com/static/;换成root /var/www/example.com/static/;那访问/static/a.png时Nginx会去找/var/www/example.com/static/static/a.png直接404。还有一个更隐蔽的坑alias使用后面必须以/结尾。alias /var/www/example.com/static和alias /var/www/example.com/static/在拼接时前者可能case出来/var/www/example.com/statica.png这种错误的路径。所以我的习惯是alias后面永远带斜杠root后面永远不带。4.3 动静分离的进阶形态前端静态项目 后端API现代前后端分离项目里动静分离的含义已经进一步升级了。前端构建产物Vue/React的dist目录全是静态文件交给Nginx直接读后端接口走/api/前缀Nginx反向代理到后端服务。这种场景下的配置骨架是这样server { listen 80; server_name admin.example.com; # 前端静态资源 root /opt/frontend/dist; index index.html; # 单页应用路由回退刷新子路由不会404 location / { try_files $uri $uri/ /index.html; } # 后端 API 反向代理 location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 60s; proxy_connect_timeout 5s; } }这里proxy_pass结尾加不加/也有讲究。如果写成proxy_pass http://127.0.0.1:8080;Nginx会把完整的URI包括/api/前缀传给后端如果写成proxy_pass http://127.0.0.1:8080/;Nginx会去掉/api/前缀再转发后端拿到的就是去掉前缀后的路径。两者对应完全不同的后端设计后端如果是直接用原始URI路由的框架比如大多数Go的net/http就用不带/的写法后端如果定义的路由是/users而非/api/users就用带/的写法。部署Vue3项目时还有一个常见的坑前端路由如果是history模式没有#用户直接访问/about刷新页面时Nginx找不到/about这个物理文件会返回404。上面配置里的try_files $uri $uri/ /index.html;就是为了解决这个问题的它会把所有找不到的请求回退到index.html让前端路由接管。5. 踩坑实录三个高频问题与完整排查链路LNMP排错最忌讳的就是瞎改配置试运气。下面这三个问题是我在真机上踩过后总结出完整排查链路的按这个顺序查能少走大量弯路。5.1 502 Bad Gateway从进程到权限一步步核502的报错意思是“Nginx作为网关没能从上游PHP-FPM拿到有效响应”。查到502第一反应不是改Nginx配置而是先确认PHP-FPM到底是死是活。排查链路我一般按这个顺序走# 第一步确认 PHP-FPM 进程是否在运行 ps aux | grep php-fpm # 第二步确认监听状态 ss -ln | grep -E 9000|php-fpm # 如果用的是Unix Socket看socket文件 ll /run/php-fpm/www.sock # 确认socket文件存在且属主是nginx # 第三步看PHP-FPM错误日志 tail -n 100 /var/log/php-fpm/error.log # 第四步单独用命令行测试FPM的返回 curl -I http://127.0.0.1/index.php最常见的结果分三种进程没起来systemctl start php-fpm即可但要顺手查日志搞清楚为什么起不来最常见是php.ini或php-fpm.conf语法错误。进程活着但socket文件属主不对Nginx worker以nginx用户运行而socket文件属主是apache或root就必然502。这个直接回头看/etc/php-fpm.d/www.conf里user和listen.owner配置。进程活着socket也没错但SCRIPT_FILENAME指向的文件不存在比如fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;里的$document_root和你实际文件路径不匹配。这时php-fpm错误日志里会明确写出“Primary script unknown”修正root或SCRIPT_FILENAME路径即可。5.2 504 Gateway Timeout超时不只是PHP的问题504和502不同它表示PHP-FPM“响应太慢”让Nginx等得不耐烦了。处理这个问题的思路不是一味加大超时时间而是先搞清楚PHP脚本为什么慢。先看几条跟超时有关的配置fastcgi_connect_timeout 60s; # 连接PHP-FPM超时 fastcgi_send_timeout 120s; # 发送请求体到PHP-FPM超时 fastcgi_read_timeout 120s; # 读取PHP-FPM响应超时以及PHP侧的配置php.inimax_execution_time 60 ; 单次脚本最大执行时间 max_input_time 60 ; 接收请求数据最大时间 memory_limit 256M ; 内存上限脚本跑了太久还会触及这个如果你发现是某个导出功能、报表统计功能经常504那属于正常的长时间脚本不要再死磕调大超时时间了正确做法是把这个任务改造成异步队列前端只返回“任务已提交”真正跑数放到后台。但如果你发现所有请求都莫名变慢那就得回到PHP-FPM进程池占用率和MySQL慢查询上查。我遇到过最离谱的一次是MySQL的innodb_buffer_pool_size被调太小导致每次查询都要反复读磁盘整个LNMP链路的翻车表象是到处超时但根因根本不在Nginx。5.3 静态文件404先区分是Nginx没找到还是权限拒绝静态文件404的排查比502要简单一些但它有个容易混淆的点404也可能是文件存在但Nginx无权读。这时候Nginx错误日志里会有两种截然不同的记录/post/static/a.png failed (13: Permission denied) # 这是权限问题 /post/static/a.png failed (2: No such file or directory) # 这是真的文件不存在权限问题的标准处理链路过一遍确认目录的r-x权限可进入可读取、文件权限至少r--、所有者的属主和被root/nginx访问的关系。一个常用命令# 查看路径里每一层目录的权限 namei -l /var/www/example.com/static/a.pngnamei这个命令可以一次性显示路径每一级目录的权限和属主比ls -l一层层敲要高效得多。常规要求是从/到文件的所有路径级目录都要有x权限如果文件属主是root且权限是600那nginx用户读不了需要chmod 644或chown nginx:nginx。文件不存在的404十有八九是root/alias的路径拼错了。先把location ^~ /static/的alias指到正确目录再访问时观察Nginx错误日志里的实际路径你在哪一步发现的偏差通常就是路径拼接的偏差。6. 上线前的安全加固与性能调优配置调通只是第一步上线前有两类工作不做后面迟早要出事。一类是安全加固另一类是性能参数调优。6.1 安全版本更新、信息隐藏与目录权限先说版本问题。Nginx这种基础设施级软件CVE公告出来之后官方通常会在小版本里修复。我记得有一段时间Nginx被曝出过HTTP/2相关的漏洞后来修复版本很快跟进如果生产环境一直停留在老版本就等于裸奔。热搜词里也有人提到CVE-2025-1695、SF-0005-22843这类编号我的建议是无论什么平台安装完第一件事就是nginx -v查看版本号然后去官方CHANGES文件核对是否已经包含对应修复版本。如果明确受影响升级是小版本操作不要拖。安全加固的常规操作可以做成一张清单逐条过项目配置方式说明隐藏版本号server_tokens off;防止攻击者根据版本号定向打漏洞HTTP头部限制移除不必要的Server详情Nginx自身响应头会变成nginx限制上传体积client_max_body_size 10m;防大文件上传拖垮后端仅允许必要请求方法limit_except GET POST { deny all; }禁止DELETE/PUT等不需要的方法PHP脚本执行权限location ~ \.php$只放在项目目录内避免上传目录里的php被执行目录列表关闭autoindex off;防止/static/目录被浏览数据库最小权限见3.3节不用root连库其中“上传目录禁止执行PHP”这条特别容易忽略。很多站点结构里有一个/uploads/目录用户上传文件后又能访问如果上传目录配了PHP解析攻击者传一个带PHP代码的文件上去URL直接访问它就相当于在服务器上执行了任意代码。规避方法location ^~ /uploads/ { location ~ \.php$ { deny all; } }嵌套location里用deny all屏蔽掉uploads目录下的所有PHP请求。注意Nginx的location是允许嵌套的这种嵌套方式比在根配置里通过if判断要清晰得多。6.2 性能进程数、连接数、压缩与缓存动态请求交给PHP-FPM后静态资源的性能就全看Nginx自己了。我常用的性能参数组合worker_processes auto; # 有多少CPU核就起多少worker worker_rlimit_nofile 65535; events { use epoll; worker_connections 10240; multi_accept on; # 一次accept接受所有新连接 } http { sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; gzip on; gzip_comp_level 5; gzip_min_length 1k; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xmlrss image/svgxml; gzip_vary on; # 静态资源的过期时间减少回源压力 map $sent_http_content_type $expires_map { default off; text/html 1h; text/css 7d; application/javascript 7d; image/jpeg 30d; image/png 30d; image/svgxml 30d; application/font-woff2 30d; } expires $expires_map; }这里worker_connections 10240和之前提到的worker_rlimit_nofile要联动看worker_processes×worker_connections就是理论上的最大连接数而每个连接都会消耗一个文件句柄所以worker_rlimit_nofile必须大于等于连接数上限否则连接没到上限就先把文件句柄耗光了。gzip压缩对文本类资源非常有效简单说就是把CSS、JS、JSON文件压缩到原来的三分之一左右但代价是CPU开销。gzip_comp_level 5是我测试下来性能和压缩比比较均衡的位置填9并不会带来多少额外的压缩收益CPU反倒吃得更狠。另外图片、视频这类本来就是二进制压缩过的资源不需要开gzip开了只会浪费CPU。Nginx 1.21.5这个版本出现在热搜词里不止一次如果用的版本恰好是它可以考虑在支持Brotli的构建版本里开启Brotli压缩。Brotli在压缩率上通常比gzip再高10%-20%但需要额外模块且客户端兼容性要注意CDN上如果开启了Brotli会更容易拿到收益。6.3 日志什么时候可以关掉access_log日志问题常常被忽视直到磁盘被占满才发现。Nginx的access_log默认记录每一个请求但如果你的站点静态资源被大量访问且又不常做访问分析日志会飞速膨胀。我的处理方式分两种一种是保留日志但做切割Linux自带logrotateNginx的rpm包安装后一般自带一个日志切割配置cat /etc/logrotate.d/nginx另一种是对特定location关掉日志。静态资源请求量最大但分析价值相对低我会在静态资源location里加一行access_log off;业务API的日志保留这样日志量能砍掉一大半。注意日志切割不是只把旧日志改名就可以必须告诉Nginx重新打开日志文件否则它还在往改名后的旧文件里写。标准做法是在logrotate配置里加上kill -USR1 $(cat /var/run/nginx.pid)。7. 上线前的全链路自检清单配置全写完不等于就可以上生产了。我把每次上线前必跑的自检清单整理成一份现在已经成了我的操作习惯每一条都是踩过的坑换来的。网络层检查[ ] 防火墙是否放行80/443端口firewall-cmd --list-ports或iptables -L -n核对[ ] SELinux是否是Enforcing如果是检查httpd_can_network_connect是否开启否则Nginx反代PHP-FPM/Socket时会被SELinux拒绝[ ] 域名解析是否已指向当前机器dig example.com short确认Nginx层检查[ ]nginx -t配置语法通过[ ]systemctl reload nginx后ps aux | grep nginx能看到worker进程数量与CPU核数一致[ ] 关闭server_tokens off后的响应头是否隐藏了版本号curl -I验证[ ] 访问一个不存在的php文件确认返回404而不是200空内容避免PHP伪静态解析漏洞PHP层检查[ ]php -v确认版本与php-fpm -t确认语法[ ]/var/log/php-fpm/error.log没有sock或primary script unknown相关报错[ ] 用php -m确认需要的扩展已经安装特别是mysqli、pdo_mysql、curl、gdMySQL层检查[ ]mysql -u app_user -p -h 127.0.0.1 -e SHOW DATABASES;能通过TCP方式连接[ ]mysql -u app_user -p -e SHOW DATABASES;能通过Socket方式连接[ ] 执行一次简单的SELECT 1确认没有权限问题[ ] 备份策略已生效mysqldump定时任务能正常产出备份文件业务层检查[ ] 首页能打开无500/502/504[ ] 一个静态资源CSS/JS/图片能直接访问响应头带Cache-Control或Expires[ ] 一个动态接口PHP/API能返回预期数据不走静态缓存[ ] 刷新一个前端history路由能正常显示而不是404[ ] 查询Nginx access_log确认动静请求分别落到了预期位置这套清单跑完才算一个能交付的LNMP环境。我在不同环境里部署过很多次LNMP最大的体会是这个系统并不复杂但它要求你对每一层的边界有清晰的认识。Nginx不是万能瑞士军刀它善于做它该做的事——处理静态连接和转发PHP-FPM管动态脚本MySQL管数据。动静分离之所以重要是因为它让每层各司其职这才是Nginx这套架构能够支撑高并发的根本。最后再分享一个贯穿始终的小建议遇到任何诡异问题先看日志不要盲目改配置。Nginx的错误日志、PHP-FPM的错误日志、MySQL的慢查询日志三层日志按时间线对齐90%的问题都能定位到根因。把这套环境亲手从头到尾搭三遍你对Nginx的认知会完全不一样。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

云南旅行社评估体系与避坑指南 2026/9/14 19:25:32

云南旅行社评估体系与避坑指南

1. 项目背景与价值解析作为一个在旅游行业摸爬滚打8年的从业者,我深知选择靠谱旅行社对旅行体验的决定性影响。去年带队考察云南市场时,我们团队花了3个月时间实地走访了37家当地旅行社,最终整理出这份"云南旅行社口碑榜"。这不是简…

阅读更多 →
使用 Rube MCP 自动化 Amcards 业务操作:awesome-codex-skills 的 amcards-automation 技能实战指南 2026/9/14 19:25:32

使用 Rube MCP 自动化 Amcards 业务操作:awesome-codex-skills 的 amcards-automation 技能实战指南

使用 Rube MCP 自动化 Amcards 业务操作:awesome-codex-skills 的 amcards-automation 技能实战指南 【免费下载链接】awesome-codex-skills A curated list of practical Codex skills for automating workflows across the Codex CLI and API. 项目地址: https:…

阅读更多 →
LiveKit Agents for Python 实战:用 AgentSession 构建生产级实时语音 AI Agent 2026/9/14 19:25:32

LiveKit Agents for Python 实战:用 AgentSession 构建生产级实时语音 AI Agent

LiveKit Agents for Python 实战:用 AgentSession 构建生产级实时语音 AI Agent 【免费下载链接】agents A framework for building realtime voice AI agents 🤖🎙️📹 项目地址: https://gitcode.com/GitHub_Trending/agen/a…

阅读更多 →
仓颉编程语言:全场景智能开发的核心特性与实践 2026/9/14 19:25:32

仓颉编程语言:全场景智能开发的核心特性与实践

1. 仓颉编程语言的核心定位与设计哲学仓颉编程语言作为面向全场景智能的新一代编程语言,其设计理念源于对现代软件开发痛点的深度洞察。在移动互联网向万物互联演进的过程中,开发者面临着多设备适配、性能优化、安全防护等多重挑战。传统编程语言往往需要…

阅读更多 →
餐饮数字化中的协同过滤推荐算法实践 2026/9/14 19:25:32

餐饮数字化中的协同过滤推荐算法实践

1. 项目概述:当推荐算法遇上餐饮数字化这个毕业设计选题巧妙地将协同过滤算法与餐饮行业数字化转型需求相结合。我十年前第一次接触推荐系统时,还是在电商平台做商品推荐,没想到现在连点菜都能用上智能推荐了。这个系统本质上是通过分析用户历…

阅读更多 →
深入优化CSS动画性能:利用transform与opacity避开重排重绘 2026/9/14 19:22:32

深入优化CSS动画性能:利用transform与opacity避开重排重绘

1. 动画卡顿的根源:浏览器如何绘制一帧1.1 帧时间的真相:60fps是如何被打破的做前端的朋友应该都遇到过类似的场景:明明只是给元素加了个hover放大效果,或者写了个简单的过渡动画,结果在 Chrome 里一跑,画面…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞