前段时间,我抢了一台腾讯的轻量云服务器,本来都已经把本站迁移过去了,但结果发现那台机器的性能实在太差了,动不动就卡爆,只好回退到阿里云这边了。通过这次迁移,我倒是把整个过程走了一遍,积累了一些经验。同时,也让我重新考虑换服务器的事。这仔细一琢磨啊,现用的阿里云确实有点贵啊!
于是,最近我一直在留意合适的 VPS,还试过一些小厂商的机器,但性能测试和实际使用下来都不太行,虚标的情况挺严重。前两天看到群里有人推百度云 BCC 的大促活动,价格特别便宜。4C4G40G3MB 配置能带 Windows Server 的版本,首年只要¥36...这价格买不了上当买不了吃亏,顺手下了一台。
接着几天,我有空就对这台 BCC 做测试,最后发现竟然堪用,于是决定把阿里云上所有的业务,包括数个网站、Docker 等应用都迁移过去。这当然涉及到很多工作…包括域名备案、环境搭建等等,但本文只着重记录我是如何进行性能测试和优化 WordPress 服务器的,如有更好的办法,先行感谢分享不吝赐教了...🙏🙏🙏
1. Web 服务器性能测试
网上有各种各样的服务器性能测试方法和脚本,对于 Web 服务器来说,常用的工具无非就是 sysbench、iostat、fio 等等。我琢磨了一下,利用 AI 写了个脚本,能够直观地输出数据,方便进行对比。
当然,这个测试并不严谨,但我主要是为了自用,而且测试的对象是 Web 服务器。所以,把这些数据拿来做横向对比,尤其是和现有服务器相比,能够很清楚地看出差异。你只需要将以下命令行保存为可执行的 .sh 文件,比如 server_bench.sh,然后运行,就能得到截图所示的结果。
#!/bin/bash
# 综合服务器性能测试脚本(by shephe.com)
# 颜色定义
GREEN='\033[0;32m'
BLUE='\033[0;34m'
RED='\033[0;31m'
NC='\033[0m'
# 工具检查
check_tools() {
local tools=("sysbench" "iostat" "curl" "fio" "dd" "ping" "mysql")
local missing_tools=()
for tool in "${tools[@]}"; do
command -v "$tool" >/dev/null 2>&1 || missing_tools+=("$tool")
done
if [ ${#missing_tools[@]} -ne 0 ]; then
echo -e "${RED}[错误] 缺少必要工具:${missing_tools[*]},请先安装。${NC}"
exit 1
fi
}
# 清理临时文件
cleanup() {
rm -f test_io test_fio 2>/dev/null
}
trap cleanup EXIT
check_tools
echo -e "\n${BLUE}=== 🖥️ 系统概况 ===${NC}"
echo -e "主机名: $(hostname)"
echo -e "系统: $(lsb_release -d 2>/dev/null | awk -F'\t' '{print $2}' || uname -srmo)"
echo -e "CPU: $(lscpu | grep 'Model name' | awk -F':' '{print $2}' | sed 's/^[ \t]*//')"
echo -e "CPU 核数: $(nproc)"
echo -e "内存: $(free -h | awk '/Mem:/ {print $2 " (可用: " $7 ")"}')"
echo -e "磁盘:"
lsblk -d -o NAME,SIZE | grep -v 'NAME' | awk '{print " - " $1 ": " $2}'
echo -e "内核版本: $(uname -r)"
echo -e "当前负载:$(uptime | awk -F'load average:' '{print $2}' | sed 's/,//g')"
echo
echo -e "${BLUE}=== ⚙️ CPU 测试(10 秒) ===${NC}"
echo -e "单线程性能:"
sysbench cpu --threads=1 --time=10 run | grep "events per second" | awk -F':' '{print " 事件/秒: " $2}'
echo -e "多线程性能(共 $(nproc) 核):"
sysbench cpu --threads=$(nproc) --time=10 run | grep "events per second" | awk -F':' '{print " 事件/秒: " $2}'
echo -e "${BLUE}=== 🧠 内存测试(读写各 1GB) ===${NC}"
echo -e "内存读取:"
sysbench memory --memory-total-size=1G --memory-oper=read run | grep "transferred" | awk '{print " " $0}'
echo -e "内存写入:"
sysbench memory --memory-total-size=1G --memory-oper=write run | grep "transferred" | awk '{print " " $0}'
echo
echo -e "${BLUE}=== 💽 磁盘 IO 测试(顺序+随机) ===${NC}"
echo -e "顺序写入:"
dd if=/dev/zero of=test_io bs=4M count=128 conv=fdatasync 2>&1 | grep copied | awk '{print " " $0}'
echo -e "顺序读取:"
dd if=test_io of=/dev/null bs=4M 2>&1 | grep copied | awk '{print " " $0}'
cleanup
echo -e "随机读写(fio):"
fio --name=randrw --rw=randrw --bs=4k --size=256M --numjobs=1 --runtime=10 --time_based --group_reporting \
--filename=test_fio --ioengine=libaio --iodepth=4 | grep -E 'read: IOPS|write: IOPS' \
| awk '{print " " $1" IOPS="$3, "BW="$5}'
cleanup
echo
echo -e "${BLUE}=== 🌐 网络性能测试 ===${NC}"
echo -e "下载速度:"
download_bytes=$(curl -o /dev/null -s -w "%{speed_download}" https://download.z.weixin.qq.com/app/win/wetype_installer_official_p_48.exe)
if [[ "$download_bytes" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
download_mib=$(awk "BEGIN {printf \"%.2f\", $download_bytes / 1024 / 1024}")
echo -e " 速度: ${download_mib} MiB/s"
else
echo -e " 下载失败或 curl 输出异常"
fi
echo -e "Ping 测试(到 223.5.5.5):"
ping -c 4 223.5.5.5 | grep 'rtt' | awk -F'/' '{print " 平均延迟: "$5" ms"}'
echo
echo -e "${BLUE}=== 🗄️ 数据库性能测试(MySQL) ===${NC}"
MAX_RETRY=3
MYSQL_USER="root"
MYSQL_DB="sysbench_test"
MYSQL_PASS=""
for ((i=1; i<=MAX_RETRY; i++)); do
read -s -p "请输入数据库 root 密码(回车跳过): " MYSQL_PASS
echo
if [[ -z "$MYSQL_PASS" ]]; then
echo -e "跳过数据库测试。"
break
fi
echo -e "尝试连接数据库..."
if mysql -u$MYSQL_USER -p$MYSQL_PASS -e ";" 2>/dev/null; then
echo -e "✅ 连接成功,准备执行测试..."
mysql -u$MYSQL_USER -p$MYSQL_PASS -e "CREATE DATABASE IF NOT EXISTS $MYSQL_DB;" 2>/dev/null
echo -e "准备测试数据..."
sysbench oltp_read_write --table-size=100000 --db-driver=mysql \
--mysql-user=$MYSQL_USER --mysql-password=$MYSQL_PASS \
--mysql-host=localhost --mysql-db=$MYSQL_DB prepare >/dev/null
echo -e "执行数据库基准测试(10 秒):"
sysbench oltp_read_write --table-size=100000 --db-driver=mysql \
--mysql-user=$MYSQL_USER --mysql-password=$MYSQL_PASS \
--mysql-host=localhost --mysql-db=$MYSQL_DB --time=10 --threads=4 run \
| grep -E 'transactions:.*per sec|queries:.*per sec' \
| awk '{print " " $1" "$2" "$3}'
echo -e "清理测试数据..."
sysbench oltp_read_write --table-size=100000 --db-driver=mysql \
--mysql-user=$MYSQL_USER --mysql-password=$MYSQL_PASS \
--mysql-host=localhost --mysql-db=$MYSQL_DB cleanup >/dev/null
mysql -u$MYSQL_USER -p$MYSQL_PASS -e "DROP DATABASE IF EXISTS $MYSQL_DB;" >/dev/null
break
else
echo -e "${RED}密码错误,第 $i 次尝试失败。${NC}"
if [[ $i -eq $MAX_RETRY ]]; then
echo -e "${RED}已达到最大重试次数,跳过数据库测试。${NC}"
fi
fi
done
echo -e "\n${GREEN}🎉 所有测试完成:$(date '+%Y-%m-%d %H:%M:%S')${NC}"
以上 .sh 命令行会检查并调用 sysbench iostat fio 等工具,因此如果你没装过的话,先执行以下命令行安装(仅适用于 Debian / Ubuntu 服务器,其他发行版适当改改就行):
sudo apt-get install sysbench sysstat fio -y



从上面的测试结果来看,BCC 的纸面数据明显优于我当前使用的 Aliyun ECS。无论是单线程还是多线程,BCC 的处理能力都更强,更适合高负载、高并发的应用。同时,BCC 在 内存性能 上也占有优势,读取和写入速度都高于 Aliyun。在 磁盘 I/O 性能 上,BCC 的顺序读取速度大幅领先,达到了 13.5 GB/s,而 Aliyun 仅为 4.9 GB/s。虽然 Aliyun 在顺序写入方面与 BCC 相近,但整体磁盘性能依然较弱。
不过,这个测试结果虽然有参考价值,但也不完全准确。我在 Aliyun 的后台管理面板查到,系统盘被分配了 3000 IOPS,而 BCC 的系统盘为 2120 IOPS,数据差异让这个测试结果显得有些模糊。
在实际建站测试中,三者的差距则更加明显。为了确保公平,我尽量保持了系统环境的一致性(如 LNMP 版本和 PHP 扩展配置),测试站除域名外其他完全一样。Aliyun 的页面生成时间比 BCC 快了约 1/5,比 Racknerd 快了约 2/3。这里提到的页面生成时间是指 PHP 渲染页面的时间,可以通过函数 timer_stop(0) 或安装 Query Monitor 来查看。我试了很多方法,但无论如何调整,BCC 都表现得稍慢一些。关于如何调整的详细内容,请参考本文第三章。
你可能要说数据库查询时间对页面生成时间的影响…这么说吧,Aliyun 的数据库查询时间最长,但它的页面生成最快!所以这是怎么回事儿呢?有没有大牛提点一下…按我现在的测试,只能把原因归结到环境和性能差异了。
2. WordPress 服务器环境搭建
不管怎样,这台百度智能云服务器的性能还是不错的。在实际使用中,我通过果果日记(登录管理员)整站测试,首页页面生成时间为 0.32 秒。相比阿里云的 0.28 秒,略慢一些,但完全可以接受。
而且,非管理员用户将启用 FastCGI 缓存,这会大大提升性能。因此,我决定将阿里云上的业务整体迁移到百度云。在此之前,我已经在 BCC 上搭建了完整的环境,并做了一些基础的系统优化。相关优化内容请参见下表:
- 系统环境:宝塔面板、LNMP、Docker
- 增强扩展:Memcached、Opcache、fileinfo
- 应用软件:phpMyAdmin、宝塔网站监控报表、Nginx 防火墙、日志清理工具、Xray
除了 Xray,其余都是非常常见的扩展和软件,没有什么特别之处。近期,GFW 的封锁越来越严格,而且免费的 Docker 镜像源也越来越难找,GitHub 的速度也慢得令人抓狂。因此,我直接一步到位安装了代理(服务端为 V2Ray,运行在 Racknerd 上),并修改了 Docker 的环境变量来实现全局代理。
同时,我还写了一个小脚本,并给脚本添加了别名。这样,在 git、shell 或 apt 中需要使用代理时,只需要通过 proxy_on/off/status 命令来切换,非常方便。/root/proxy_toggle.sh脚本如下:
#!/bin/bash
# 代理一键开关:当前 shell + git + apt
# 用法:source /root/proxy_toggle.sh on|off|status
# 关闭时不破坏原有网络与配置(自动备份并恢复)
PROXY_URL="${PROXY_URL:-http://127.0.0.1:7890}"
# 状态与备份文件
STATE_DIR="${HOME}/.config/proxy_toggle"
STATE_FILE="${STATE_DIR}/state.env"
mkdir -p "$STATE_DIR"
# apt 代理文件(我们只动这一个)
APT_PROXY_CONF="/etc/apt/apt.conf.d/80proxy-toggle"
# 判断是否 source 执行
is_sourced() { [[ "${BASH_SOURCE[0]}" != "${0}" ]]; }
# 需要 root 权限时决定是否用 sudo
need_root_cmd() {
if [[ $EUID -eq 0 ]]; then
"$@"
else
if command -v sudo >/dev/null 2>&1; then
sudo "$@"
else
echo "⚠️ 需要 root 权限执行:$* (未安装/配置 sudo)" >&2
return 1
fi
fi
}
# 读取旧状态(若存在)
load_state() {
if [[ -f "$STATE_FILE" ]]; then
# shellcheck source=/dev/null
source "$STATE_FILE"
fi
}
# 保存当前状态
save_state() {
cat > "$STATE_FILE" <<EOF
ACTIVE="${ACTIVE:-0}"
PREV_HTTP_PROXY="$(printf %s "${PREV_HTTP_PROXY}")"
PREV_HTTPS_PROXY="$(printf %s "${PREV_HTTPS_PROXY}")"
PREV_GIT_HTTP_PROXY="$(printf %s "${PREV_GIT_HTTP_PROXY}")"
PREV_GIT_HTTPS_PROXY="$(printf %s "${PREV_GIT_HTTPS_PROXY}")"
EOF
}
# ---------- shell 环境 ----------
enable_shell_env() {
# 备份仅在第一次启用时记录
if [[ "${ACTIVE:-0}" != "1" ]]; then
PREV_HTTP_PROXY="${http_proxy}"
PREV_HTTPS_PROXY="${https_proxy}"
fi
export http_proxy="$PROXY_URL"
export https_proxy="$PROXY_URL"
}
disable_shell_env() {
# 恢复:若原来有值则还原,没有就 unset
if [[ -n "${PREV_HTTP_PROXY}" ]]; then
export http_proxy="${PREV_HTTP_PROXY}"
else
unset http_proxy
fi
if [[ -n "${PREV_HTTPS_PROXY}" ]]; then
export https_proxy="${PREV_HTTPS_PROXY}"
else
unset https_proxy
fi
}
# ---------- git 代理 ----------
enable_git_proxy() {
if [[ "${ACTIVE:-0}" != "1" ]]; then
PREV_GIT_HTTP_PROXY="$(git config --global --get http.proxy 2>/dev/null || true)"
PREV_GIT_HTTPS_PROXY="$(git config --global --get https.proxy 2>/dev/null || true)"
fi
git config --global http.proxy "$PROXY_URL" 2>/dev/null || true
git config --global https.proxy "$PROXY_URL" 2>/dev/null || true
}
disable_git_proxy() {
if [[ -n "${PREV_GIT_HTTP_PROXY}" ]]; then
git config --global http.proxy "${PREV_GIT_HTTP_PROXY}" 2>/dev/null || true
else
git config --global --unset http.proxy 2>/dev/null || true
fi
if [[ -n "${PREV_GIT_HTTPS_PROXY}" ]]; then
git config --global https.proxy "${PREV_GIT_HTTPS_PROXY}" 2>/dev/null || true
else
git config --global --unset https.proxy 2>/dev/null || true
fi
}
# ---------- apt 代理(独立文件,不覆盖你的原配置) ----------
enable_apt_proxy() {
need_root_cmd bash -c "cat > '$APT_PROXY_CONF' <<EOF
Acquire::http::Proxy \"$PROXY_URL\";
Acquire::https::Proxy \"$PROXY_URL\";
EOF" || return 1
}
disable_apt_proxy() {
need_root_cmd rm -f "$APT_PROXY_CONF" || return 1
}
# ---------- 显示状态 ----------
show_status() {
echo "=== Shell ==="
echo "http_proxy=${http_proxy:-<empty>}"
echo "https_proxy=${https_proxy:-<empty>}"
echo
echo "=== git (global) ==="
git config --global -l 2>/dev/null | grep -E '^(http|https)\.proxy=' || echo "git 无代理配置"
echo
echo "=== apt ==="
if [[ -f "$APT_PROXY_CONF" ]]; then
echo "(已启用) $APT_PROXY_CONF 内容:"
need_root_cmd cat "$APT_PROXY_CONF" 2>/dev/null || true
else
echo "apt 无代理配置(我们的 80proxy-toggle 未启用)"
fi
echo
echo "PROXY_URL=${PROXY_URL}"
echo "提示:若 Shell 变量为空,请使用:source $0 on"
}
# ---------- 主逻辑 ----------
load_state
case "$1" in
on)
# 必须 source 才能让当前 shell 变量生效
if ! is_sourced; then
echo "💡 请使用:source $0 on"
exit 1
fi
enable_shell_env
enable_git_proxy
if enable_apt_proxy; then
ACTIVE="1"
save_state
echo "✅ 代理已开启(shell + git + apt) -> $PROXY_URL"
else
echo "⚠️ apt 代理未能写入(可能缺少 root/sudo),但 shell+git 已启用"
fi
;;
off)
if ! is_sourced; then
echo "💡 请使用:source $0 off"
exit 1
fi
# 先恢复/清理
disable_shell_env
disable_git_proxy
if disable_apt_proxy; then
:
else
echo "⚠️ 未能删除 apt 代理文件(可能缺少 root/sudo),请手动处理:$APT_PROXY_CONF"
fi
ACTIVE="0"
save_state
echo "❌ 代理已关闭(已恢复原有 shell/git,删除我们创建的 apt 代理文件)"
;;
status|*)
show_status
;;
esac
设置别名的脚本如下:
alias proxy_on='source /root/proxy_toggle.sh on'
alias proxy_off='source /root/proxy_toggle.sh off'
alias proxy_status='source /root/proxy_toggle.sh status'
看看实际的运行效果:

3. WordPress 服务器性能优化
注意审题,这里只对 WordPress 服务器的性能进行优化,确切的讲,我只优化“页面生成时间”这一个指标,因此不涉及 CDN、数据库缓存什么的。上文提到,我“做了很多测试”,才把这个指标干到 0.32s,实际上一开始它接近 2s!
我主要安装了 PHP opcache 扩展,它的作用是把 PHP 脚本编译后的 Opcode(操作码) 缓存在内存中。这样同一个脚本在后续请求时就不需要再次解析和编译,直接执行缓存的字节码,从而显著提升 PHP 应用的性能、降低 CPU 消耗。
对于像 WordPress 这类高频访问的站点,开启 OPcache 能够明显缩短页面生成时间,是必备的优化手段之一。对于我上面 Aliyun 和 BCC 这样配置的服务器来说,经过我数次的测试,我总结 PHP 配置和 FPM 配置这样写比较快:
[Zend Opcache]
zend_extension=/www/server/php/82/lib/php/extensions/no-debug-non-zts-20220829/opcache.so
opcache.enable = 1
opcache.memory_consumption=256
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=100000
opcache.revalidate_freq=60
opcache.validate_timestamps=1
opcache.fast_shutdown=1
opcache.enable_cli=0
opcache.file_update_protection=0
opcache.save_comments=1
opcache.jit_buffer_size=256m
opcache.jit=1255
[global]
pid = /www/server/php/82/var/run/php-fpm.pid
error_log = /www/server/php/82/var/log/php-fpm.log
log_level = notice
[www]
listen = /tmp/php-cgi-82.sock
listen.backlog = 8192
listen.allowed_clients = 127.0.0.1
listen.owner = www
listen.group = www
listen.mode = 0600
user = www
group = www
pm = dynamic
pm.status_path = /phpfpm_82_status
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 20
request_terminate_timeout = 100
request_slowlog_timeout = 30
slowlog = var/log/slow.log

当然,这个配置还跟 PHP 版本也有关系,作为外行,我是凭浏览器刷新页面,查看函数和插件反馈的时间慢慢调的,单次刷新当然不准,后来我搞了个 PHP 脚本,可以获取到平均刷新几十次的数据,就准一些了了。
这是一个在 LNMP 环境下进行 PHP 页面生成时间基准测试 的小工具。它的用途主要是:在真实服务器环境中,批量请求指定的 URL,并统计后端执行耗时,用于对比不同服务器(例如 BCC vs 阿里云)在相同代码和数据下的性能差异。测试结果会输出 min / p50 / p90 / max / avg 等关键指标,便于分析性能稳定性和尾延迟,脚本下载 ⏬。
4. WordPress 网站迁移记录
4.1 WordPress 站点迁移
网站迁移没啥可说的,无非就是备份数据库、打包文件、上传下载啥的,当然也可以宝塔的整站迁移…不过效率都差不多,我在「服务器迁移记录」这篇日志里略有提及。
另外,国内主流服务器厂商,域名备案信息要跟着迁移,至少百度这边特别敏感…我解析了几分钟不到,就收到短信给我把域名停掉了,提示了必须迁移备案。上次搞腾讯好像没这么严格,只要是备案了不管你备案在哪儿,都能先用着…不晓得长期用会不会要求迁移,没试过。
4.2 Docker 应用迁移
当前服务器上有 Certimate、AwesomeTTRSS、Memos、Twikoo 这几个容器,前两个把核心数据记住,推导重建然后在 Web 面板直接导入数据就行。这 Memos 现在没怎么用了,而且据说新版和旧版并不兼容,我想直接放弃得了。
我的 Memos 其实也没多少人看,也没几个留言,我干脆截图、在主站即当前 Kevin's Space 写篇日志得了,就这么放弃了,还免得维护了。得,就这么办喽~
5. 其他应用安装
主要有 Syncthing、FRP 等等。

[…] WordPress 服务器性能测试优化方案 & 迁移记录 08/26/2025 […]