1. 项目概述:为什么要折腾一台“真正可用”的Linux服务器
去年我帮一个朋友部署线上业务,他手里有一台配置还不错的Linux服务器——16核32G内存,系统是Rocky Linux。机器到手半个月,除了开个SSH挂着,什么业务都没跑,问他打算干嘛,他说“等我想好了再装环境”。这种状态我见过太多次了:服务器买了、系统装了,但离“真正可用”还差着十万八千里。裸机不是服务器,只是一台开着机的电脑。让服务器真正跑起来,第一步就是搭好基础服务栈。
这篇文章就围绕一个最常见的组合展开:Nginx + MySQL + PHP + WordPress。这是莱AMP(Linux + Nginx + MySQL + PHP)体系里最经典的搭配之一,能覆盖个人博客、企业官网、CMS内容管理、甚至小型电商站点的需求。选择WordPress倒不是说它技术上限有多高,而是它足够“有感”:装完之后你能立刻看到网页在跑、后台能登录、文章能发布,整个链路从请求到数据库再到PHP处理,每个环节都是可见的。对新手来说,这种即时反馈比干巴巴的“部署成功”四个字有价值得多。
这篇博文适合谁看?两类人。第一类是刚接触Linux服务器、想从零搭一套Web环境的初学者,我会把每一步操作、每个参数为什么这么配都讲清楚;第二类是已经会装基础环境、但常被权限、PHP-FPM并发、MySQL连接数、WordPress迁移等细节绊住的人,后面几章的问题排查和调优实录就是为你们准备的。
整个部署过程大约半小时能完成(取决于服务器带宽和下载速度),不需要复杂的前置条件,一台能跑Linux的机器、一个root账号、一个域名(没有就用IP先顶着)、还有一点点耐心就够了。下面开始。部署环境我以Rocky Linux 9 / CentOS Stream 9这类RHEL系系统为例,Debian/Ubuntu系的命令差异我会在关键节点提示。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 整体设计:LNMP架构为什么这么搭,以及部署前的准备
2.1 架构选型与核心逻辑
先回答一个最常见的问题:同样能跑网站的Apache也能干这个活儿,为什么选Nginx?
Nginx和Apache的最大区别在于并发处理模型。Apache是多进程模型,每个连接占用一个进程或线程,内存开销随连接数线性增长;Nginx则是事件驱动模型,一个进程能同时处理成千上万个连接,本质上是异步非阻塞I/O。用一个生活化的类比:Apache像是银行柜台,一个柜员只服务一个客户,客户多了就得排队加柜台;Nginx像一个超级柜员,手里同时处理几十个号,谁准备好了就处理谁,吞吐量完全不同。
在WordPress这个场景下,Nginx还有一个天生的优势:动静分离。WordPress的网页分成两类内容:PHP动态生成的HTML页面,和图片、CSS、JS这类静态文件。Nginx处理静态文件的能力极强,而PHP请求需要转交给PHP-FPM处理。合理的架构是:Nginx接收所有请求,如果是静态文件就直接返回,如果是PHP脚本就转给PHP-FPM进程池,PHP-FPM再调用PHP解析器执行代码,代码里需要读写数据库时,再和MySQL通信。最终结果返回给Nginx,Nginx再返回给浏览器。
这个链路就是LNMP的核心,理解它比背命令重要得多。部署的时候你可以不看这些细节,但出了问题排查时,你必须清楚请求到底卡在哪一环:是Nginx返回的502说明PHP-FPM挂了,是超时白屏说明PHP执行太慢,是数据库连接错误说明MySQL配置有问题。这些都是后面排查章节的地基。
2.2 版本选型:稳定是第一优先级
选版本这件事我吃过亏。刚接触Linux那会儿,我习惯装最新版,觉得新版本功能多、性能好。后来线上环境暴露出兼容性问题,才知道对服务器来说,稳定压倒一切。
MySQL方面,8.0是当前主流生产版本,性能和安全性都比5.7有明显提升,但要注意8.0的认证插件默认是caching_sha2_password,老的PHP扩展和部分客户端不兼容。PHP方面,7.4以上的版本对WordPress支持良好,PHP 8.x的版本性能提升显著,但个别老插件会有兼容性问题。如果你用的是WordPress 6.x,建议装PHP 8.1或8.2,性能和兼容性能取得比较好的平衡。Nginx方面直接上最新稳定版(1.24或1.26),配置语法多年稳定,不用担心变动。
有一个建议我反复对身边朋友说:不要在生产环境用源码编译安装,除非你确实需要自定义编译参数。用系统包管理器(dnf/apt)安装的好处是依赖自动处理、后续更新简单、卸载干净。用源码编译是学习和练手的好方式,但对“让服务器真正可用”这个目标来说,那是绕远路。
2.3 部署前环境准备清单
安装之前,先把系统基础环境准备好。我不建议一拿到服务器就急着装东西,先把这四件事做了:
第一,系统更新。执行 dnf update -y(RHEL系)或 apt update && apt upgrade -y(Debian系),把系统和内核补丁打齐。很多安全问题都是旧版本系统漏洞导致的,这一步不要省。
第二,确认SELinux状态。RHEL系默认开启SELinux,配合Nginx+PHP-FPM时如果不做配置,很容易出现“网页打不开但nginx进程正常”的诡异问题。我的建议是:生产环境最好保持SELinux开启,并针对性配置;但如果你只想快速验证部署流程,可以临时设置 setenforce 0 先跑通,后面再回过头来配策略。这里需要注意,临时关闭重启后就失效了,想永久关闭需要修改 /etc/selinux/config 文件,不过我不推荐这么做。
第三,设置主机名和防火墙。主机名会出现在Nginx错误日志和PHP报错里,一个规范的主机名能帮你快速定位是哪台机器。防火墙方面,RHEL系用firewalld,Debian系用ufw,只需要放行三个端口:22(SSH)、80(HTTP)、443(HTTPS)。
第四,检查端口占用。80端口如果已经被其他服务占用,后面Nginx会起不来。可以用 ss -lntp | grep :80 检查,有冲突就提前处理。
3. 核心组件部署:Nginx、MySQL、PHP一个都不能少
3.1 Nginx安装与基础配置
RHEL系的官方源里Nginx版本通常偏旧,建议先添加Nginx官方源。操作很简单:
bash复制# 创建nginx.repo文件
cat > /etc/yum.repos.d/nginx.repo << 'EOF'
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
EOF
# 安装
dnf install -y nginx
# 设置开机自启并立即启动
systemctl enable nginx --now
启动后先验证状态:systemctl status nginx,看到 active (running) 就说明正常。然后用浏览器访问服务器IP,能看到Nginx默认欢迎页,说明Web服务已经工作了。这一步如果访问不了,优先查防火墙:firewall-cmd --list-all 确认80端口在允许列表里。
Nginx的默认配置目录结构是这样的:
bash复制/etc/nginx/
├── nginx.conf # 主配置文件
├── conf.d/ # 存放自定义配置文件
└── modules/ # 动态模块目录
我习惯在 conf.d/ 下建一个独立的站点配置文件,不要把所有站点写到主配置文件里。每个站点一个文件,命名清晰(如 wordpress.conf),后续维护、迁移、备份都方便。
3.2 MySQL 8.0安装与初始化配置
MySQL的安装同样建议用官方源。RHEL系下操作如下:
bash复制# 添加MySQL官方yum源
dnf install -y https://dev.mysql.com/get/mysql80-community-release-el9-1.noarch.rpm
# 安装MySQL社区版
dnf install -y mysql-community-server
# 启动并设置开机自启
systemctl enable mysqld --now
MySQL 8.0首次启动时会自动生成一个临时root密码,存储在日志文件里:
bash复制grep 'temporary password' /var/log/mysqld.log
拿到临时密码后,执行安全初始化脚本:
bash复制mysql_secure_installation
这个脚本会引导你完成几个关键设置:修改root密码、移除匿名用户、禁止root远程登录、删除test数据库、刷新权限表。我的建议是全部选Yes,除非你明确知道自己需要某个选项保持默认。
关于密码强度,MySQL 8.0默认要求密码至少8位、包含大小写字母、数字和特殊字符。如果你设置的密码不符合要求,会收到报错提示。不用想着绕过这个限制,通过 validate_password 组件可以调整策略,但对生产环境来说保持默认强度才是正确的选择。
装完之后,为WordPress创建专用数据库和用户,这是独立性原则的体现:应用账号和root账号分离,即使WordPress被入侵,攻击者拿到的也只是应用账号权限,无法直接操作全局数据库。
sql复制-- 登录MySQL
mysql -uroot -p
-- 创建数据库,字符集使用utf8mb4
CREATE DATABASE wordpress_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 创建专用用户并授权
CREATE USER 'wp_user'@'localhost' IDENTIFIED BY '你的强密码';
GRANT ALL PRIVILEGES ON wordpress_db.* TO 'wp_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;
注意 utf8mb4 是必选项,WordPress本身支持emoji和生僻字,这些字符在utf8mb4下才能正常存储,普通的utf8(utf8mb3)只支持基本多语言平面,存emoji会直接报错。
3.3 PHP安装与PHP-FPM配置
PHP的安装在RHEL系上有个小坑:系统自带源里的PHP版本只有7.2,太老了。建议添加Remi仓库,这是RHEL系最流行的PHP源:
bash复制# 安装EPEL和Remi仓库
dnf install -y epel-release
dnf install -y https://rpms.remirepo.net/enterprise/remi-release-9.rpm
# 启用PHP 8.2模块
dnf module reset php -y
dnf module enable php:remi-8.2 -y
# 安装PHP及常用扩展
dnf install -y php php-fpm php-mysqlnd php-gd php-xml php-mbstring php-json php-curl php-zip php-opcache
这些扩展对应WordPress的各类功能,我逐个说明用途:
php-mysqlnd:PHP操作MySQL数据库的驱动,WordPress数据读写全靠它php-gd:图像处理库,WordPress裁剪缩略图、处理媒体文件时需要php-xml:XML解析,RSS订阅、XML-RPC协议都依赖它php-mbstring:多字节字符串处理,中文站点的字符处理正确性依赖它php-curl:HTTP请求库,WordPress后台检查更新、插件自动升级需要php-zip:ZIP压缩/解压,后台安装插件和主题时用它来解包php-opcache:PHP字节码缓存,能显著提升PHP执行性能
有一个扩展这里特意列出来提醒:php-fpm 是PHP进程管理器,Nginx要执行PHP脚本就必须经过它,绝对不能漏装。
装完后检查版本确认成功:php -v。然后做基础配置。PHP-FPM的主配置文件是 /etc/php-fpm.d/www.conf,需要修改几个关键参数:
ini复制; 修改运行用户为nginx,保持与Nginx用户一致
user = nginx
group = nginx
; 监听方式改为Unix Socket,比TCP更高效
listen = /run/php-fpm/www.sock
; Socket文件权限
listen.owner = nginx
listen.group = nginx
listen.mode = 0660
; 进程管理方式为动态
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 15
pm.max_children 是最重要的性能参数,它决定了PHP-FPM最多能同时处理多少个PHP请求。这个值不是越大越好,它受服务器内存限制。每个PHP-FPM进程大约占用30-50MB内存,你的服务器是32G内存,理论上一半内存给PHP进程都够用,但实际还要留给Nginx、MySQL和其他进程。我的建议是先按内存公式估算:可用内存 / 每个进程平均占用 = max_children,比如24G可用内存除以40MB,得到600,但实际生产环境通常取50-100之间,再根据压测结果调整。
这里有一个容易踩的坑:PHP-FPM的运行用户必须和Nginx用户一致。如果PHP-FPM以apache用户运行,Nginx以nginx用户运行,访问socket文件时会因为权限问题导致502错误。统一成nginx用户是最省心的方案。
3.4 配置Nginx站点文件
配置Nginx站点是LNMP栈里最容易出错但也最关键的一步。下面是我在 conf.d/wordpress.conf 里用的完整配置,每段都加了注释说明用途:
nginx复制server {
listen 80;
# 域名,没有域名就填服务器IP
server_name your-domain.com;
# WordPress根目录
root /usr/share/nginx/html;
index index.php index.html;
# 访问日志
access_log /var/log/nginx/wordpress_access.log;
error_log /var/log/nginx/wordpress_error.log;
# 静态文件处理:存在就返回,不存在就继续交给下面的规则
location / {
try_files $uri $uri/ /index.php?$args;
}
# 图片等静态资源的缓存控制
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|webp)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
# PHP请求转交给PHP-FPM处理
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# 禁止访问隐藏文件,提高安全性
location ~ /\. {
deny all;
}
}
最核心的一行是:
nginx复制try_files $uri $uri/ /index.php?$args;
这行的意思是:如果请求的是一个真实存在的文件(比如一张图片)就直接返回;如果请求的是一个存在的目录就返回目录首页;如果以上都不满足,就把请求重写给 /index.php,并携带原始查询参数。这就是WordPress实现伪静态(友好的URL结构,如 /archives/123.html)的基础。
配置写好后,验证语法并重载:
bash复制nginx -t
systemctl reload nginx
看到 syntax is ok 就说明配置没问题。
3.5 验证PHP运行状态
在Nginx的网站根目录创建一个测试文件:
bash复制cat > /usr/share/nginx/html/info.php << 'EOF'
<?php
phpinfo();
EOF
浏览器访问 http://你的IP/info.php,能看到一个完整的PHP信息页,说明【Nginx → PHP-FPM】这条链路已经通了。里面能看到PHP版本、已加载的扩展、配置文件路径等关键信息。
看完之后立刻删掉这个文件:rm /usr/share/nginx/html/info.php。phpinfo() 会把PHP版本、扩展、环境变量等敏感信息完整暴露给访问者,这等于给攻击者递了一份服务器体检报告。这个习惯要养成:任何调试用的临时文件,用完后马上清理。
4. WordPress部署实操:从下载到上线完整流程
4.1 下载并解压WordPress
授权和下载这步,我推荐用官方源。到WordPress官网找到最新版本下载链接,然后在服务器上操作:
bash复制cd /tmp
# 下载最新版WordPress(以6.x为例)
wget https://wordpress.org/latest.tar.gz
# 解压
tar -xzf latest.tar.gz
# 将解压后的文件移动到网站根目录
cp -r wordpress/* /usr/share/nginx/html/
移动之后设置目录权限:
bash复制chown -R nginx:nginx /usr/share/nginx/html/
这个权限设置很关键。Nginx进程以nginx用户运行,如果网站目录的所有者是root,Nginx就无法正常读取文件,页面会返回403或404。chown nginx:nginx 让Nginx拥有网站目录的所有权,同时PHP-FPM(同样以nginx用户运行)也能正常写入文件——比如后台自动安装插件、生成缓存文件等。
4.2 通过Web向导完成安装
配置好目录后,浏览器访问 http://你的IP/,WordPress会自动跳转到安装引导页面。这一步需要注意的是MySQL相关信息填写:
- 数据库名:
wordpress_db - 用户名:
wp_user - 密码:你为wp_user设置的强密码
- 数据库主机:
localhost(默认即可) - 表前缀:
wp_(保持默认)
点击提交后,WordPress会尝试连接数据库并写入配置文件 /usr/share/nginx/html/wp-config.php。如果提示“无法写入配置文件”,说明目录权限没设置好,回到上一步检查 chown 是否已执行,或者用下面的方式手动创建:
bash复制cp /usr/share/nginx/html/wp-config-sample.php /usr/share/nginx/html/wp-config.php
vim /usr/share/nginx/html/wp-config.php
在文件中填写数据库连接信息即可。
接下来是站点信息设置:站点标题、管理员用户名、密码、邮箱。这里给个建议:管理员用户名不要用admin,这个用户名是攻击者暴力破解的首选目标。用字母加数字组合,比如 fan_2024_admin 这种格式,能有效提高安全性。
安装完成后,你的WordPress站点就正式上线了。你可以登录后台(http://你的IP/wp-admin),写第一篇文章、更换主题、安装插件,开始真正使用这台服务器了。
4.3 使用域名访问的配置
如果使用域名访问,在WordPress后台的“设置 → 常规”里,把站点地址和WordPress地址从IP改成你的域名。但要注意,不要在没有做好域名解析之前修改这个地址,否则你和WordPress的连接就断了——因为后台会强制把请求重定向到新域名,而新域名根本没解析到你的服务器。
正确做法是:先到域名服务商那里把A记录解析到服务器IP,确认 ping 你的域名 能返回服务器IP,再修改后台地址。改完之后马上用域名访问试试,能打开说明配置成功。如果打不开,检查Nginx配置里的 server_name 是否包含你的域名。
4.4 启用HTTPS(可选但推荐)
现在的站点,不启用HTTPS基本等于裸奔。WordPress站点启用HTTPS有两条路径:
最简单的是用Certbot自动申请Let's Encrypt免费证书:
bash复制dnf install -y certbot python3-certbot-nginx
certbot --nginx -d your-domain.com
Certbot会自动修改Nginx配置、配置证书自动续期,整个过程只需要回答几个问题。我用过很多次,实测最省心。
如果你不想用Certbot,也可以手动申请其他厂商的免费证书,然后把证书文件路径配置到Nginx的 listen 443 ssl; 配置块里。后者灵活性更高,但配置步骤更多,这里就不展开细说了。
4.5 安全加固清单
上线之后别急着宣传,先把安全基础打好。下面是我给每台WordPress服务器都会做的加固操作:
第一,修改文件权限到最严。WordPress官方建议:目录权限755,文件权限644,wp-config.php 保持440。执行:
bash复制find /usr/share/nginx/html -type d -exec chmod 755 {} \;
find /usr/share/nginx/html -type f -exec chmod 644 {} \;
chmod 440 /usr/share/nginx/html/wp-config.php
第二,禁用XML-RPC。这个功能以前用于远程发布,现在大多数场景用不上了,但它是暴力破解的重灾区。在Nginx配置里加一条规则:
nginx复制location ~* xmlrpc\.php$ {
deny all;
}
第三,启用WordPress防火墙插件。我用过Wordfence和Cloudflare,Wordfence的免费版就够用,能拦截恶意请求、检测文件篡改、限制登录尝试次数。安装后记得配置邮件通知,安全事件能第一时间知道。
第四,登录入口二次保护。最简单是在Nginx层面加访问限制,只允许特定IP访问 wp-login.php,但这对个人用户不够友好,因为家庭IP经常变动。折中方案是:启用WordPress自带的两步验证插件或者安装一个登录验证码插件,给登录入口加一层防护。
5. 常见问题与排查技巧实录
5.1 Nginx返回502 Bad Gateway
症状:访问页面提示502。
原因:Nginx无法连接到PHP-FPM。最常见的原因是PHP-FPM没有启动,或者Socket文件路径不一致。
排查步骤:
bash复制# 检查PHP-FPM状态
systemctl status php-fpm
# 确认Socket文件存在
ls -l /run/php-fpm/www.sock
# 检查Nginx错误日志
tail -n 50 /var/log/nginx/error.log
看到错误日志里有 connect() failed (111: Connection refused) while connecting to upstream,说明PHP-FPM没运行或者监听地址不对。启动PHP-FPM后,再看Socket文件是否存在、Nginx配置里的 fastcgi_pass 路径是否与实际一致。我用这个思路解决了至少十次502问题,每次都有效。
5.2 Nginx返回403 Forbidden
症状:访问网站返回403。
原因:Nginx没有权限读取网站目录,或目录下没有index文件。如果第一步部署用的是IP访问,最容易出的就是这个错。
排查步骤:
bash复制# 检查目录权限
ls -ld /usr/share/nginx/html
# 确认目录下有index.php文件
ls -l /usr/share/nginx/html/index.php
# 检查Nginx运行用户
ps aux | grep nginx
如果目录属主是root,Nginx以nginx用户访问,就会403。执行前面提到的 chown -R nginx:nginx /usr/share/nginx/html/ 即可解决。还有一种情况是SELinux拦截,检查 /var/log/audit/audit.log,如果有 denied 记录,使用 ausearch 结合 chcon 或 setsebool 处理。
5.3 页面能打开但全是乱码
症状:网页能打开,但中文全部显示为问号或乱码。
原因:字符集不匹配。多数情况下是数据库字符集设置不对,或者PHP与MySQL交互时字符集没对齐。
排查步骤:
bash复制# 查看数据库字符集
mysql -uroot -p -e "SHOW CREATE DATABASE wordpress_db;"
如果显示不是 utf8mb4,重建数据库或修改字符集:
sql复制ALTER DATABASE wordpress_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
还要检查 wp-config.php 里是否定义了数据库字符集:
php复制define('DB_CHARSET', 'utf8mb4');
define('DB_COLLATE', '');
另外,Nginx配置里也建议加上 charset utf-8;,多一层保险。
5.4 MySQL连接数超限:Too many connections
症状:日志报错 Too many connections。
原因:MySQL的连接数被占满,常见于慢查询堆积或应用没有及时释放连接。WordPress站点访问量突增,或某个插件写入了低效的SQL查询就很容易触发。
排查步骤:
bash复制# 查看当前连接数
mysql -uroot -p -e "SHOW VARIABLES LIKE 'max_connections';"
mysql -uroot -p -e "SHOW STATUS LIKE 'Threads_connected';"
# 查看当前所有连接来自哪
mysql -uroot -p -e "SHOW FULL PROCESSLIST;"
如果是并发确实高,调大 max_connections,在 /etc/my.cnf 的 [mysqld] 段下加:
ini复制max_connections = 500
但调大值只是治标,真正的元凶往往是慢查询。开启MySQL慢查询日志,定位哪些SQL拖慢了数据库:
ini复制slow_query_log = ON
slow_query_log_file = /var/log/mysql-slow.log
long_query_time = 2
找到慢SQL后,结合执行计划分析是否需要加索引,或者优化WordPress插件配置。这是治本的方向。
5.5 上传文件大小限制
症状:WordPress后台无法上传大于2MB的图片或主题压缩包。
原因:PHP默认上传限制是2MB。
解决方法:修改PHP配置文件,在 /etc/php.ini 里调整:
ini复制upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
max_execution_time = 300
改完重启PHP-FPM生效。如果用的是Nginx,还要检查Nginx配置里是否有 client_max_body_size 限制,有的话也要调大。
5.6 无法安装插件或主题
症状:后台尝试安装插件/主题时,提示“无法创建目录”或要求输入FTP信息。
原因:PHP进程没有网站目录的写权限,或者WordPress无法直接写入文件。
解决方法:
bash复制# 确认目录属主
chown -R nginx:nginx /usr/share/nginx/html/
# 在wp-config.php中定义FTP方式直写
define('FS_METHOD', 'direct');
把 FS_METHOD 设为 direct,让WordPress直接使用PHP的写入能力安装文件,不需要通过FTP通道。这是解决WordPress安装插件权限问题最常见的做法。
5.7 排查技巧:如何系统定位故障环节
最后分享一套我自己的排查方法:LNMP的问题,本质上都可以归结为请求在哪个环节断掉了。我的排查顺序永远是:
- 看Nginx错误日志:
/var/log/nginx/error.log,先知道Nginx层面发生了什么 - 看PHP-FPM日志:
/var/log/php-fpm/error.log,排除PHP执行层面的异常 - 看MySQL错误日志:
/var/log/mysql/mysqld.log,没有数据库报错再往下走 - 看PHP-FPM进程是否存活:
ps aux | grep php-fpm - 看端口监听状态:
ss -lntp | grep -E ':80|:3306'
这套逻辑的核心是:从最外层向内逐层逼近。Nginx是最先接触请求的,它出了问题,后面的PHP和MySQL根本不会被执行。先解决Nginx层,再往上走,效率最高,不会在多个环节间来回跳。
6. 性能优化:让WordPress跑得更快的几个关键调整
6.1 PHP-FPM调优
PHP-FPM是LNMP里最影响性能的环节,但它也是最容易配置错的。这里的核心是 pm.max_children 和 pm.max_requests。
pm.max_requests 这个参数容易被忽视:它指的是每个PHP-FPM子进程在处理多少个请求后自动重启。设置它的意义在于防止长期运行的进程出现内存泄漏——PHP执行完脚本后会释放变量,但有些扩展的内存没有完全释放,进程运行时间越长,内存占用越高。设置 pm.max_requests = 1000 左右,让进程在积累一定请求后自动回收,可以避免内存缓慢泄漏导致服务器越来越卡。
6.2 Nginx开启Gzip压缩
Gzip是性价比最高的性能优化手段,配置也最简单。在Nginx配置的 http 段里加上:
nginx复制gzip on;
gzip_comp_level 5;
gzip_min_length 1024;
gzip_proxied any;
gzip_vary on;
gzip_types
text/plain
text/css
application/json
application/javascript
application/xml
image/svg+xml;
开启后,Nginx会在返回HTML/CSS/JS前先压缩,传输体积能减少60%-70%。对于带宽有限的服务器,效果立竿见影。测试方法:用浏览器开发者工具看响应头,出现 content-encoding: gzip 就说明生效了。
6.3 缓存方案选择
WordPress是动态生成内容的,每次请求都要执行PHP脚本、查询数据库。高并发下,这种动态生成会成为性能瓶颈。解决思路是缓存:把生成好的HTML页面保存下来,下次直接返回静态页面,不用再走PHP和MySQL。
WordPress缓存插件里,我实际用过且推荐的是LiteSpeed Cache和WP Super Cache。如果你的Nginx里安装了LiteSpeed模块,LiteSpeed Cache的缓存命中率极高;如果用纯Nginx,WP Super Cache也能实现页面级缓存。
缓存插件的工作原理可以简单理解为一个“快递柜”:第一次用户访问时,把生成的包裹(HTML)放进柜子;后续用户来取件时直接从柜子拿,不用再让仓库(PHP+MySQL)重新打包。配置完缓存后,网站响应时间通常能从几百毫秒降到几十毫秒。
6.4 MySQL参数优化
MySQL默认配置适合开发环境,不适合生产。在 /etc/my.cnf 里加以下几个关键参数:
ini复制[mysqld]
innodb_buffer_pool_size = 4G
innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 2
query_cache_type = 0
transaction_isolation = READ-COMMITTED
这些参数的含义:
innodb_buffer_pool_size:InnoDB的缓冲池大小,是MySQL最重要的内存参数,用于缓存数据和索引。经验值是物理内存的50%-70%,你的服务器32G内存,设16G甚至更大都合理,但要根据实际给PHP和Nginx留出余量innodb_log_file_size:事务日志文件大小,大小会影响写入性能。日志文件太小,每次事务提交都要频繁切换日志文件,性能差innodb_flush_log_at_trx_commit = 2:降低日志刷盘频率,提升写入性能,代价是极端断电场景可能丢失1秒内的数据。对博客这类应用场景可接受
修改后重启MySQL生效:systemctl restart mysqld。
6.5 调整内核参数(可选)
服务器并发连接数高时,调整几个内核参数能明显改善稳定性。编辑 /etc/sysctl.conf:
ini复制net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_tw_reuse = 1
fs.file-max = 1000000
执行 sysctl -p 生效。这几个参数的作用是:扩大Nginx接受连接的能力、加快TIME_WAIT状态的socket回收,避免端口耗尽。注意,tcp_tw_reuse要谨慎使用,它只对客户端产生的TIME_WAIT连接有效,服务端生成的不受影响。
7. 后续维护:服务器不是装完就结束的
部署完成不是终点,日常维护才真正考验一个人的运维习惯。下面几点是我自己坚持做的事情,分享给你们。
7.1 建立备份机制
备份是运维的底牌,没有备份的服务器就是定时炸弹。WordPress站点备份主要备份两部分:网站文件和数据库,两者缺一不可。
推荐用crontab定时备份,下面是我常用的备份脚本思路:
bash复制#!/bin/bash
# 备份WordPress文件
tar -czf /backup/wordpress_$(date +%Y%m%d).tar.gz /usr/share/nginx/html/
# 备份数据库
mysqldump -uroot -p你的密码 wordpress_db > /backup/db_$(date +%Y%m%d).sql
# 保留最近30天备份,清理旧文件
find /backup -type f -mtime +30 -delete
写入crontab,每天凌晨执行:
bash复制0 3 * * * /usr/local/bin/backup_wordpress.sh
还要考虑异地备份:把备份文件同步到另一个存储节点(对象存储、另一台服务器都行),防止服务器硬件故障导致备份文件一起丢失。这个环节我这边的经验是:本地备份保底,异地备份兜底,两个都做完才敢说备份这事落实了。
7.2 系统与软件更新
WordPress、插件、主题、PHP、MySQL、Nginx,这些都是需要持续更新的软件,漏洞修补大多通过版本更新完成。我的更新策略:
- WordPress及插件:后台自动更新打开,核心版本安全更新自动推送,插件更新提交到测试环境验证后再更新到生产
- 系统补丁:每周执行一次
dnf update -y,更新后重启服务确认状态 - PHP和Nginx:关注官方安全公告,有安全更新及时处理
更新前记得备份,更新后测试访问,这个流程别省。
7.3 日志分析与监控预警
日志是最好的体检报告。Nginx访问日志记录了所有请求,PHP错误日志记录了执行异常,MySQL慢查询日志记录了性能瓶颈。定期查看这些日志能提前发现问题和攻击痕迹。
监控方面,我只推荐一个最简方案:crontab定时检查关键服务状态,出问题就发邮件通知。下面是一段简单的监控脚本:
bash复制#!/bin/bash
if ! systemctl is-active nginx > /dev/null; then
echo "Nginx挂了" | mail -s "Nginx service down" your-email@example.com
systemctl restart nginx
fi
写成服务检查脚本,每5分钟运行一次。这个方法简单有效,适合个人服务器,不用额外装监控系统。
7.4 性能压测:知道你的服务器极限
部署完成后,花点时间压测一下,了解服务器的性能边界。压测工具有很多,ab、wrk、jmeter都行,最简单的是ab:
bash复制# 安装ab
dnf install -y httpd-tools
# 并发100,总共发送10000个请求
ab -n 10000 -c 100 http://你的IP/
测试结果里重点看 Requests per second 和 Time per request。第一次压测能跑到多少不重要,重要的是记录基线和话,后续每次调整参数后再压一次,对比是否有提升。这会让你对服务器的性能有真实的感知,而不是靠感觉调优。
注意:压测是给服务器施压的过程,建议在业务低峰期进行,避免影响线上访问。
8. 最后:几个让我少踩坑的经验
文章写到这里,LNMP基础和WordPress部署的完整流程已经走完了。按步骤操作,你应该已经拥有一台能跑起来、能写文章、能自定义主题的服务器了。最后分享几个我踩过坑后的经验,这些在官方文档里通常不会写。
关于用IP还是域名:如果只是测试环境,用IP访问完全没问题;如果想长期使用,早点绑定域名、启用HTTPS,不要等到内容多了才迁移,迁移过程远比想象中麻烦。
关于SELinux:网上很多教程教你直接关闭SELinux,我的建议是生产环境别关。虽然SELinux配置确实有学习成本,但它是RHEL系系统安全的重要防线。遇到SELinux拦截问题时,先从 ausearch -m avc 定位具体被拦截的进程和文件,再针对性地放行,比直接关闭好得多。
关于服务器密码:设置强密码、启用SSH密钥登录、关闭密码登录,这三件事做完,服务器被暴力破解的风险能降低90%以上。WordPress后台也要设置强密码,最好开启两步验证。安全不是靠单一措施实现的,而是多层防护叠加后的结果。
关于遇到问题的心态:服务器报错不可怕,可怕的是因为害怕而不敢尝试。每一条错误日志都是有用的信息,你在排查过程中积累的判断力,才是运维水平提升的真正体现。
现在,你的服务器已经从“开机即吃灰”变成了真正可用的Web服务器。接下来该做什么就很简单了:写文章、做项目、或者研究其他服务的部署,继续折腾起来。
