尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
LNMP架构全解析:从请求原理到性能调优与排错实战
1. 我为什么要从LAMP切换LNMP架构选型中的得与失很多朋友来问我说现在做网站环境搭建到底是选LAMP还是LNMP。我最早接触这行的时候也是从LAMP入手的Apache配置起来逻辑直观一个虚拟主机一个VirtualHost.htaccess放进去规则就生效对初学者极其友好。但后来网站量上来之后我发现一个问题Apache的进程模型在对付高并发静态请求时太吃力了一个进程对应一个连接连接多了内存和CPU就双双告急。后来把前端服务器换成了Nginx后端依然用Apache处理动态请求的架构也试过一段时间。那套组合虽然能用但中间多了一层反向代理的转发Apache的进程开销照样省不掉整体效果并不理想。直到我把后端也换成PHP-FPM整条链路变成Nginx PHP-FPM MySQL/MariaDB才真正感受到这套架构在资源占用和并发能力上的优势。LNMP这个缩写代表的就是Linux服务器系统、Nginx服务器软件、MySQL或MariaDB数据库以及PHP动态语言环境。如果你要维护的站点对并发有一定要求或者你想在一台配置普通的云服务器上跑更多业务LNMP几乎是一个绕不开的架构选择。这里必须说清楚一件事LNMP和LAMP不是简单的谁取代谁而是各自适用的场景不同。Apache的模块化机制让它在处理复杂重写规则、用户认证这类功能时非常灵活.htaccess也能让非管理员用户在自己目录里做配置。而Nginx走的是事件驱动模型一个worker进程可以同时服务成千上万个连接静态文件的处理能力非常强但它对动态请求本身不感兴趣所以必须交给PHP-FPM去执行。换句话说Nginx更像一个高效的前台接待PHP-FPM才是真正干活的车间。在动手搭建之前我建议你先明确自己的需求只有一个跑PHP的小站点还是准备承载一定的流量服务器内存是512MB还是2GB以上需不需要一台机器上部署多个站点、每个站点隔离运行这些问题会直接影响后面的安装方式、PHP-FPM进程模型的选择甚至Nginx配置的写法。我把这套笔记按我自己的学习路径整理出来从请求原理讲到实际配置再讲到排错和优化希望能帮你把LNMP这条链路彻底吃透。2. LNMP请求链路拆解Nginx、PHP-FPM与FastCGI是怎么串起来的2.1 一个HTTP请求从进入Nginx到返回页面的完整旅程理解LNMP最关键的不是会敲安装命令而是搞懂一次用户请求从浏览器发出到页面渲染出来中间到底经历了什么。我第一次搭LNMP时就犯过这样的错以为Nginx配置好、PHP装好、数据库起来就能跑结果访问PHP页面直接下载源码文件完全没走解析流程。这就是没理解Nginx和PHP之间交接机制导致的。一次完整的请求大概是这样的浏览器发起请求DNS解析域名后连接服务器的80或443端口Nginx在监听这些端口。Nginx根据请求的域名和URI通过server块和location规则做路由判断。如果请求的是静态资源比如图片、CSS、JS文件Nginx直接自己处理从磁盘读取文件返回不经过PHP。如果请求的是PHP脚本Nginx就会通过FastCGI协议把请求交给PHP-FPM去处理。PHP-FPM的master进程接收到请求后从进程池里调度一个空闲的worker进程来执行这个请求。worker进程读取PHP文件如果需要访问数据库再通过PHP的MySQL扩展和MySQL/MariaDB通信拿到数据后执行逻辑处理。PHP执行完毕把生成的HTML结果沿原路返回给NginxNginx再响应给浏览器。这里最核心的就是第4步。Nginx本身根本不认识PHP代码它只负责把请求翻译成一个FastCGI请求通过fastcgi_pass指令指定的地址送给PHP-FPM。PHP-FPM解析并处理完之后同样通过FastCGI协议把结果返回。这个协议层就是两者之间的交接柜台。2.2 FastCGI协议和PHP-FPM的角色分工我在学习这一段时找了很久的资料发现很多人把FastCGI和PHP-FPM混为一谈。它们是两个层面的东西FastCGI是一种协议它定义了Web服务器和动态语言进程之间如何通信PHP-FPM是PHP官方提供的FastCGI进程管理器是协议的实现者。PHP-FPM下很常见的方式有两种一种是Unix Socket方式一种是TCP端口方式。我在配置文件中经常看到类似这样的写法fastcgi_pass unix:/var/run/php-fpm/www.sock;或者fastcgi_pass 127.0.0.1:9000;前者是Unix Socket通信后者是TCP端口通信。Socket方式省去了TCP握手和网络协议栈的开销在同一台服务器上性能更好TCP方式则允许PHP-FPM运行在其他机器上适合拆分部署的场景。在同一台服务器的标准LNMP部署里我习惯用Unix Socket延迟更低。PHP-FPM的分工也很明确master进程负责管理worker进程比如监听网络端口或socket、接受Nginx转交来的请求、分配任务worker进程负责实际执行PHP脚本。worker进程的数量和调度方式由pm指令控制。理解了这个分层后续遇到502 Bad Gateway时你才会知道大概率是PHP-FPM掉了或者worker进程处理不过来而不是Nginx本身出了问题。3. CentOS 7上从零搭起一套LNMP安装与基础配置实操3.1 选包管理器还是源码编译我的判断依据网上很多LNMP教程上来就是源码编译三件套configure、make、make install一编译就是一下午。我早期也迷信过源码编译感觉这样干净可控但后来维护的环境多了发现源码编译的代价很大升级PHP版本时要重新编译某个扩展要开启也要重新编译遇到依赖问题更是头大。对我这种追求可维护性的人来说用发行版官方仓库加上可信的第三方源通过包管理器安装反而是更稳妥的路子。要说清楚的是源码编译并非没有优点比如可以精确控制PHP的编译参数、启用哪些扩展、安装在哪个目录。但这种细致程度的控制在多数业务场景下是用不上的反而包管理器能把依赖处理得明明白白卸载、升级都方便。我现在的做法是测试环境用包管理器快速搭生产环境遇到特殊扩展需求才单独走源码编译。本文整套搭建基于CentOS 7.9PHP从官方源安装7.4版本数据库用MariaDB 10.3系列。CentOS 7的默认软件源里自带的PHP版本是5.4实在太老所以需要额外添加软件源的仓库文件。这里我用了EPEL源和Remi源。EPEL是Extra Packages for Enterprise Linux的软件源Remi源则专注于提供较新版本的PHP。安装步骤如下yum install -y epel-release rpm -Uvh https://rpms.remirepo.net/enterprise/remi-release-7.rpm yum install -y yum-utils yum-config-manager --enable remi-php74 yum install -y nginx php php-fpm php-mysqlnd php-mbstring php-xml php-gd php-opcacheNginx在EPEL源里就是最新可用版本不需要额外折腾。MySQL我用MariaDB替代兼容性没任何问题命令和MySQL基本一致yum install -y mariadb mariadb-server3.2 把基础服务启动起来并做好开机自启安装完成后先不要急着改各种配置先把三个核心服务启动验证一遍。启动命令如下systemctl start nginx systemctl start php-fpm systemctl start mariadb systemctl enable nginx systemctl enable php-fpm systemctl enable mariadbenable的作用是设置开机自启CentOS 7里用systemd管理服务这步不要漏。启动之后在浏览器里访问服务器的IP地址如果能看见Nginx的默认欢迎页说明Nginx工作正常。PHP-FPM有没有起来可以看进程或者socket文件ps aux | grep php-fpm ls -l /var/run/php-fpm/www.sock如果socket文件存在说明PHP-FPM已经成功监听。这里有一个新手容易踩的坑装完Nginx和PHP-FPM之后两者的运行用户可能不一致。Nginx默认以nginx用户运行PHP-FPM默认以apache用户运行这会导致PHP无法读取Nginx站点目录下的文件或者Nginx无法访问PHP-FPM生成的socket文件。我在配置阶段会把这几个用户统一起来后面第4节会详细讲。3.3 数据库初始化别忘了给root设置密码MariaDB装完后直接mysql命令是可以免密进入的这显然不行。执行自带的初始化安全脚本mysql_secure_installation这个脚本会一步步引导你设置root密码、删除匿名用户、禁止root远程登录、删除测试数据库。我建议全部选择Yes。之后再用密码登录验证一下mysql -uroot -p到这里LNMP的三个核心服务就已经全部跑起来了。这一步的基本配置不需要改任何配置文件先把环境跑通再去动细颗粒度的配置会更有成就感排查问题也更容易。4. Nginx站点配置的细节从伪静态到PHP文件执行路径梳理4.1 一个规范server块该写哪些内容LNMP的优势很大程度体现在Nginx极致的配置灵活度上。先看一份我常用的站点配置模板每个项目一个文件放在/etc/nginx/conf.d/下面文件名以域名命名比如web.mydomain.com.confserver { listen 80; server_name web.mydomain.com; root /var/www/web; index index.php index.html; access_log /var/log/nginx/web_access.log; error_log /var/log/nginx/web_error.log; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { root /var/www/web; fastcgi_pass unix:/var/run/php-fpm/www.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 7d; access_log off; } }这份配置几乎覆盖了LNMP最核心的使用场景。server_name用于匹配域名root定义了站点的根目录index指定了目录请求时默认找哪个文件。location /里的try_files是LNMP伪静态的关键所在当请求的路径不是一个真实存在的文件、也不是一个真实目录时就统一重写到/index.php由PHP前端控制器去路由。这在部署ThinkPHP、Laravel这类现代PHP框架时是标准写法。4.2 PHP location的匹配规则与常见错误重点看PHP的location写法location ~ \.php$ { root /var/www/web; fastcgi_pass unix:/var/run/php-fpm/www.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; }正则\.php$表示匹配所有以.php结尾的URI。fastcgi_pass指定了PHP-FPM的监听地址fastcgi_index指定了如果请求只是一个目录时默认找的PHP入口最关键的一行是fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;。这一行设置了FastCGI协议里一个非常重要的参数SCRIPT_FILENAME告诉PHP-FPM要执行的脚本在磁盘上的绝对路径。很多人在配置Nginx和PHP时遇到File not found错误或者页面直接空白十有八九是SCRIPT_FILENAME设置不对。常见的错误写法是把$document_root写成了别的路径或者没写这一行直接用了默认配置。要记住$document_root取的是当前server块里root指令的值$fastcgi_script_name取的是请求的URI两者拼接才得到完整的脚本路径。如果root写到了location内部也要保持一致否则就会出现Nginx按A路径找文件、PHP-FPM按B路径执行的情况最终结果就是404或File not found。我在这一节踩过的最深刻的一个坑是在location里重新定义了root但外面的location /里的root是另一个路径。结果访问首页一切正常访问子目录下PHP文件全部404。排查半天后才发现是内外root不一致导致的。维护多站点时建议每个站点的root路径都写清楚不要依赖默认值也不要在不同location里写不同的root。4.3 运行用户统一与目录权限的强制性要求Nginx的worker进程以什么用户运行决定了它能读取哪些文件。PHP-FPM的worker进程以什么用户运行决定了PHP脚本能以什么权限执行文件操作。默认情况下Nginx用nginx用户PHP-FPM用apache用户这在大多数场景下没问题但遇到需要PHP写文件的情况比如写入缓存目录、上传图片目录就会权限不足。我的习惯是把PHP-FPM的监听用户改成和Nginx一致。编辑/etc/php-fpm.d/www.confuser nginx group nginx listen /var/run/php-fpm/www.sock listen.owner nginx listen.group nginx listen.mode 0660修改后重启PHP-FPMsystemctl restart php-fpm接着给站点目录设置合理的权限。比如站点根目录是/var/www/web我通常用以下权限模型chown -R nginx:nginx /var/www/web find /var/www/web -type d -exec chmod 755 {} \; find /var/www/web -type f -exec chmod 644 {} \;也就是说目录755、文件644即可。需要站点运行时写入的目录比如runtime、upload、cache这些单独把权限放宽chmod -R 775 /var/www/web/runtime chown -R nginx:nginx /var/www/web/runtime这样既保证PHP能写入必要的目录又避免了整个站点目录777的过度宽松权限。很多安全扫描工具会把777目录标记为高风险加上SELinux如果开着还会阻止Nginx读取某些文件所以权限设置要做到够用且最小化。5. 数据库层的例行操作初始化、账号划分与和PHP的配合5.1 创建业务账号和安全基线配置LNMP里数据库的角色经常被忽视。不少新手直接把root账号写在PHP代码里连库这是非常危险的习惯。我的做法是每个业务单独建一个数据库账号权限只给这个业务需要的库。用root登录MariaDB后执行CREATE DATABASE webdb DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER webuserlocalhost IDENTIFIED BY StrongPassword; GRANT ALL PRIVILEGES ON webdb.* TO webuserlocalhost; FLUSH PRIVILEGES;这里用webuserlocalhost限定了只允许从本机连接防止数据库账号被外网暴力破解后直接登录。GRANT只授权webdb这一个库即使账号泄露影响面也被控制住了。字符集方面我在学习早期吃过亏。数据库、表、连接三层的字符集如果不统一中文很容易出现乱码。上面建库时已经指定了数据库级字符集建表时也要注意。PHP连接数据库时在PDO连接串里要加上编码参数$dsn mysql:host127.0.0.1;port3306;dbnamewebdb;charsetutf8mb4;utf8mb4和utf8的区别在于前者支持emoji和更多特殊字符现在的新项目可以直接默认utf8mb4。排序规则utf8mb4_unicode_ci比utf8mb4_general_ci对多语言支持更准确虽然性能上略逊一点但日常业务感知不到差异。5.2 连接方式的选择与常见连接报错PHP连接MySQL有mysqli和PDO两种主流方式我推荐用PDO。原因很简单PDO不仅支持MySQL还能在将来更换数据库时减少代码改动且支持预处理语句在防SQL注入方面更顺手。这里列一个PDO连接的最简示例try { $pdo new PDO( mysql:host127.0.0.1;port3306;dbnamewebdb;charsetutf8mb4, webuser, StrongPassword, [ PDO::ATTR_ERRMODE PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES false, ] ); } catch (PDOException $e) { error_log($e-getMessage()); exit(数据库连接失败请稍后重试); }PDO::ATTR_EMULATE_PREPARES设为false表示让MySQL原生完成预处理能有效提升安全性。ERRMODE_EXCEPTION让PDO在出错时抛出异常方便开发和排错。这段代码里有一个细节值得注意host填127.0.0.1时PDO走TCP连接host填localhost时PHP在某些环境下会尝试走Unix Socket连接。如果数据库监听的不是默认socket路径连接就会报socket相关的错误。遇到这类连接问题时先用命令行验证数据库账号本身能否登录mysql -uwebuser -p -h127.0.0.1 webdb然后再检查PHP代码里的连接参数这一步能快速区分是账号问题还是代码问题。5.3 数据库层次的日常运维建议数据库上线后不是装完就完事了。我给自己定了一个例行清单备份、慢查询日志、端口暴露检查。备份是最基本的我用crontab每天凌晨全量备份mysqldump -uroot -p... --single-transaction --routines --triggers webdb | gzip /backup/webdb_$(date %F).sql.gz--single-transaction用于InnoDB表保证备份过程中不锁表。备份文件和加密后的数据库密码都不能放到站点目录下最好单独存到只有root能访问的目录。慢查询日志能帮你抓到拖慢业务的SQL。修改/etc/my.cnfslow_query_log 1 slow_query_log_file /var/log/mariadb-slow.log long_query_time 2long_query_time表示超过2秒的SQL会被记录下来。日志文件会增长很快我习惯用logrotate做轮转防止磁盘被日志占满。6. 上线前的性能调优清单进程数、缓存与缓冲的平衡之道6.1 PHP-FPM进程池的三种模式怎么选LNMP调优里面PHP-FPM的进程管理是最值得花时间研究的一块。/etc/php-fpm.d/www.conf里的pm指令控制进程池的工作方式有三种模式。我在不同服务器上都试过这里直接说结论。pm static固定worker进程数量。进程数不会动态增减对流量波动有心理预期的场景最稳定因为避免了频繁创建销毁进程的开销。pm dynamic动态调整设置一个起始数量、最大空闲数、最小空闲数和最大进程数。PHP-FPM会根据空闲进程数动态fork或杀掉worker。pm ondemand有请求来了才创建进程空闲超时后回收。适合流量很小、内存紧张的机器但请求高峰期会因为进程创建产生延迟。我目前的主流配置是dynamic配合以下参数pm dynamic pm.max_children 80 pm.start_servers 20 pm.min_spare_servers 10 pm.max_spare_servers 40 pm.max_requests 5000max_children的数值不是拍脑袋定的。一个PHP-FPM worker进程大约会占20MB到80MB内存取决于PHP扩展和业务代码复杂度。在2GB内存的服务器上按每个进程60MB估算80个进程刚好接近满载。计算公式我通常这样用max_children (服务器内存 - 系统常驻内存 - MySQL内存) / 单个worker平均内存pm.max_requests 5000的意义在于每个worker处理5000次请求后自动重启避免PHP脚本或扩展的内存泄漏逐渐累积。6.2 Nginx侧的worker进程、Gzip与缓存配置Nginx自身的调优相对简单。/etc/nginx/nginx.conf里worker_processes auto;让Nginx按照CPU核心数自动启动worker通常一个核心一个worker。worker_connections可以适当调大events { worker_connections 4096; }在虚拟机或低配服务器上别盲目调大数值worker连接数只是上限不代表实际占用。真正占资源的是打开的文件描述符必要时同步调整/etc/security/limits.conf里的nofile限制。开启Gzip压缩对静态文本类资源的效果立竿见影gzip on; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xmlrss image/svgxml; gzip_min_length 1024; gzip_comp_level 5;gzip_comp_level不用设置太高5左右是压缩比和CPU开销的平衡点设到9对多数小资源文件来说收益很小。PHP侧的缓存我强烈推荐开启OPcache。PHP是解释型语言每次请求都要经历词法解析、语法解析、编译成opcode的过程。OPcache能在内存里缓存编译后的opcode省掉重复编译的开销。CentOS上用Remi源安装的PHP自带/etc/php.d/10-opcache.ini确认配置如下opcache.enable 1 opcache.memory_consumption 128 opcache.interned_strings_buffer 16 opcache.max_accelerated_files 10000 opcache.revalidate_freq 606.3 FastCGI Cache与MySQL查询缓存的实际收益Nginx还支持FastCGI Cache将PHP生成的页面缓存起来。对动态页面全站缓存来说这是利器但对交互性强的站点要慎用。我一般只针对不登录用户的公共页面开配置思路是在server块里定义缓存路径和缓存规则fastcgi_cache_path /var/cache/nginx levels1:2 keys_zonefcgi:100m inactive10m; fastcgi_cache_key $scheme$request_method$host$request_uri; server { ... location ~ \.php$ { set $skip_cache 0; if ($request_uri ~* (login|logout|admin)) { set $skip_cache 1; } fastcgi_cache fcgi; fastcgi_cache_valid 200 60m; fastcgi_cache_bypass $skip_cache; fastcgi_no_cache $skip_cache; } }注意缓存key的定义漏掉$request_method可能导致POST请求也命中缓存产生逻辑错误。踩过一次之后我对缓存key的写法格外谨慎。MySQL的查询缓存在MariaDB 10.3还是默认开启的。针对读多写少的场景可以适当调大query_cache_sizequery_cache_size 64M query_cache_limit 2M但高并发写入场景下查询缓存的全局锁反而会成为瓶颈这类业务直接把query_cache_type设为0关闭即可。7. LNMP踩坑实录502/504/403/404的完整排查链路7.1 502 Bad Gateway八成是PHP-FPM的问题502是LNMP环境里出现频率最高的错误我在论坛里看到求助帖十有八九是这个。502的核心含义是Nginx把请求交给了FastCGI后端但后端没有给出有效响应。排查思路按顺序走第一确认PHP-FPM进程还活着systemctl status php-fpm ps aux | grep php-fpm如果进程数只有master没有worker或者master也没了看日志tail -50 /var/log/php-fpm/error.log常见原因包括socket文件被误删、listen权限不对、内存耗尽导致进程被OOM Killer杀掉。后者在低配服务器上尤其常见dmesg | grep -i oom能确认。第二确认Nginx的fastcgi_pass和PHP-FPM的listen地址一致。一个监听socket一个走TCP端口两边对不上必然502。检查ss -lnx | grep php-fpm ss -lnt | grep 9000第三确认worker进程是否因为处理超时才导致502。PHP-FPM的request_terminate_timeout如果设得太短脚本执行超时会被强杀Nginx那边就会收到空响应。我会把它设到30秒左右并配合日志去发现真正的慢请求。7.2 504 Gateway TimeoutNginx等待太久失去耐心504和502不同它表示Nginx把请求转给了PHP-FPM但PHP-FPM在Nginx设定的时间内没有处理完。Nginx默认的fastcgi_read_timeout是60秒如果PHP脚本里有外部API调用耗时很长或者某个SQL查询没有索引导致慢查询很容易超时。排查步骤是先看是不是某个特定接口才报504如果是大概率是业务代码慢如果所有PHP页面都504那就检查Nginx的fastcgi_read_timeout配置location ~ \.php$ { fastcgi_read_timeout 120; fastcgi_send_timeout 120; fastcgi_connect_timeout 10; }同时打开PHP-FPM的慢日志定位是哪段代码慢slowlog /var/log/php-fpm/slow.log request_slowlog_timeout 5s慢日志会记录执行时间超过5秒的请求的调用栈一眼就能看到卡在哪个函数。这一步几乎百试百灵。7.3 403和404的区分一个权限问题一个配置问题403是Nginx成功收到了请求但拒绝访问资源。常见原因有三个目录或文件权限不足。Nginx worker进程没有读权限检查root目录的属主和权限。目录索引功能被关闭。访问一个没有index文件的目录时如果autoindex off默认关闭Nginx会返回403。此时要么补上index文件要么开启autoindex。SELinux拦截。CentOS 7默认SELinux是enforcing模式Nginx读取的目录如果SELinux上下文不对会被拦截。先临时验证setsebool -P httpd_can_network_connect 1或者查看SELinux的AUDIT日志grep nginx /var/log/audit/audit.log如果确认是SELinux导致的可以用chcon修改目录上下文或者排除后关闭SELinux。我建议尽量保留SELinux通过正确设置上下文解决而不是直接关掉。404则完全不同。404代表Nginx知道文件在哪但根据配置找不到匹配的文件。在LNMP环境里最典型的场景是伪静态规则没有生效导致带路由参数的请求找不到对应的物理文件。比如访问/user/profile如果try_files没配置好Nginx就会去找物理路径/user/profile发现不存在就返回404。排查方式先看HTML源码还是接口返回404再测试直接访问物理PHP文件是否正常如果物理文件正常而路由路径404问题基本锁定在伪静态配置上。7.4 一份可以保存的排查速查表我在电脑旁边贴了一张速查表遇到问题先查表再动手效率提升很大错误码含义首选排查方向502后端进程无响应PHP-FPM存活状态、socket/端口一致性504后端处理超时business代码慢、fastcgi_read_timeout403拒绝访问权限、index文件、SELinux404资源不存在root路径、伪静态规则、fastcgi SCRIPT_FILENAME500PHP内部错误PHP错误日志、语法检查空白页PHP被静默终止关闭display_errors后看日志、PHP内存限制排错的核心原则是先用日志说话再改配置。Nginx的错误日志在/var/log/nginx/error.logPHP-FPM的错误日志在/var/log/php-fpm/error.logMariaDB的日志在/var/log/mariadb/mariadb.log。这三份日志覆盖了LNMP链路的全部环节绝大多数问题都能从里面找到直接线索。7.5 LNMP排错前的检查清单这里列出我在每次动手排查前会快速确认的几项内容非常有帮助服务状态systemctl status nginx php-fpm mariadb确认三者都是active状态端口监听ss -lntp查看80端口、ss -lx查看php-fpm的socket防火墙CentOS 7默认firewalld确认80和443端口已放行firewall-cmd --zonepublic --add-servicehttp --add-servicehttps --permanent firewall-cmd --reload磁盘空间df -h日志分区如果满了Nginx经常会报奇怪错误日志时间戳排查时先确认服务器时间正确否则日志时间对不上会走弯路。这套清单用熟了之后很多问题还没走到深水区就能揪出来。我在实际维护中还发现一个容易被忽视的习惯问题修改Nginx或PHP配置后建议先用命令验证配置再重载服务。nginx -t php-fpm -t两条命令都能在重载前发现语法错误避免在改错配置后导致服务直接起不来。习惯了这套工作流之后LNMP环境的稳定性和可维护性都提升了不少遇到问题也更有底气去拆解而不是靠搜一堆零散的解决方案瞎试。
RELATED

相关推荐

决策树算法五实验:文本树可视化、特征重要性与剪枝扫描(sklearn 实测)

决策树算法五实验:文本树可视化、特征重要性与剪枝扫描(sklearn 实测)

决策树算法五实验:文本树可视化、特征重要性与剪枝扫描(sklearn 实测) 决策树是机器学习入门第一棵树,但多数教程止步于 fit score。本文五个实验覆盖训练、可解释性、调参、交叉验证全流程,sklearn 真实数据集&…

📅 2026/10/6 3:19:47
一行代码搞定文件内容提取:Java SPI + PaddleOCR 统一解析实践

一行代码搞定文件内容提取:Java SPI + PaddleOCR 统一解析实践

不知道你们有没有这种经历:后台系统里用户传进来一堆文件,Word、PDF、手机照片什么都有,产品经理云淡风轻地丢下一句“把里面的文字提取出来”,然后整个后端就开始加班。文件类型五花八门,有的能直接读文本&#xff0c…

📅 2026/10/6 3:19:47
Python+uniapp+微信小程序:心理自测咨询小程序全流程实战

Python+uniapp+微信小程序:心理自测咨询小程序全流程实战

最近把“Python uniapp 微信小程序”这个组合用在一个心理自测咨询小程序项目上,从需求拆解到后端接口、前端页面、打包上线,整个流程走了一遍,踩了不少坑,也沉淀了一些可以复用东西。这篇就把这个项目的完整思路、技术选型、关…

📅 2026/10/6 3:19:47
MORE NEWS

更多资讯

📰

Cadence Allegro 17.4 PCB封装制作全流程:从焊盘到丝印实战详解

1. 为什么封装这一步,直接决定你后面的板子能不能画得下去先把这个话题摆到桌面上:很多刚接触Cadence 17.4 Allegro的工程师,最容易犯的一个共同错误,就是急着去画原理图、摆器件、走线,结果到了布局阶段才发现——库里…

📰

Next.js静态生成实战:SSG原理到ISR配置,解决性能与SEO优化难题

最近接了个优化个人博客的活儿,首屏白屏五六秒,文章页收录率低得可怜,客户改后台配置改到头大。我最后把整站切到了 Next.js,用静态生成(SSG)重写了核心页面,效果立竿见影——构建产物里直接躺着…

📰

Redis管理工具redisplus在Windows下的安装、连接与运维排查

简介:这是一款面向Redis开发与运维人员的桌面级可视化管理工具,支持单机、集群两种连接模式,并能通过SSH通道访问远程或内网环境,日常查看键值、执行命令、监控实例状态都比纯命令行更直观。压缩包为RedisPlus 3.2.0稳定版Windows…

📰

NMOS高边开关驱动全解析:自举电容、栅极驱动芯片与PMOS选型权衡

1. 先想清楚:为什么高边开关容易想到PMOS,而不是NMOS做硬件的人对高边开关应该都不陌生:电源正极进来,先经过开关管,再接到负载,负载另一端直接接地。这种结构的最大好处是,负载任何时候都不会与…

📰

开题答辩全攻略:从报告架构到PPT设计与答辩话术

1. 开题答辩的本质:老师到底在看什么先说一个很多学生没想明白的问题:开题答辩绝不是一个“走过场”的仪式,也不是让你上去念一遍开题报告。它是你整个毕业设计的第一道关卡,老师坐在下面,真正想确认的事情只有三件——…

📰

Flask实战:构建在线云音乐系统从零到部署完整指南

1. 为什么用Flask做在线云音乐系统先说结论:用 Python 的 Flask 框架写一个在线云音乐系统,是个人练手、毕业设计、简历项目里性价比非常高的一条路。它不是那种“看起来很厉害但根本跑不起来”的空中楼阁,而是从用户注册、歌曲上传、播放器、…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬