一、为什么需要高可用架构
单点故障是Web服务的最大隐患。当服务器宕机、网络中断或应用崩溃时,没有高可用架构的网站将完全不可用。ThinkPHP作为国内主流PHP框架,其高可用部署需要从负载均衡、数据库集群、会话共享、文件同步等多个维度进行设计。
高可用核心目标:
– 零停机时间:故障自动转移,用户无感知
– 水平扩展:业务增长时快速增加节点
– 数据安全:数据库主从复制,数据零丢失
– 故障自愈:自动检测并恢复异常节点
二、整体架构设计
┌─────────────┐
│ Nginx LB │
│ (主负载均衡) │
└──────┬──────┘
│
┌────────────┼────────────┐
│ │ │
┌─────┴─────┐ ┌───┴────┐ ┌────┴─────┐
│ Node 1 │ │ Node 2 │ │ Node 3 │
│ ThinkPHP │ │ThinkPHP│ │ ThinkPHP │
│ + PHP-FPM│ │+FPM │ │ + FPM │
└─────┬─────┘ └───┬────┘ └────┬─────┘
│ │ │
┌─────┴────────────┴────────────┴─────┐
│ 共享存储层 │
│ Redis(会话) + NFS(文件) + MariaDB │
└─────────────────────────────────────┘
三、环境准备
3.1 服务器规划
| 节点 | IP地址 | 用途 | 配置建议 |
|---|---|---|---|
| LB-1 | 192.168.1.100 | Nginx主负载均衡 | 2核2G |
| LB-2 | 192.168.1.101 | Nginx备用负载均衡 | 2核2G |
| APP-1 | 192.168.1.110 | ThinkPHP应用节点1 | 4核4G |
| APP-2 | 192.168.1.111 | ThinkPHP应用节点2 | 4核4G |
| DB-M | 192.168.1.120 | MariaDB主库 | 4核8G SSD |
| DB-S | 192.168.1.121 | MariaDB从库 | 4核8G SSD |
| Redis | 192.168.1.130 | Redis会话/缓存 | 2核4G |
3.2 基础软件安装
所有应用节点执行:
# 更新系统
sudo apt update && sudo apt upgrade -y
# 安装Nginx、PHP和扩展
sudo apt install -y nginx php8.3-fpm php8.3-cli php8.3-common \
php8.3-mysql php8.3-redis php8.3-mbstring php8.3-xml \
php8.3-curl php8.3-zip php8.3-bcmath php8.3-intl \
php8.3-readline php8.3-opcache
# 验证安装
php -v
nginx -v
php-fpm8.3 -v
四、Nginx负载均衡配置
4.1 主负载均衡器配置
# /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
multi_accept on;
use epoll;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
client_max_body_size 50M;
# Gzip压缩
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml;
gzip_min_length 1000;
# ThinkPHP应用上游集群
upstream thinkphp_cluster {
# 最少连接策略
least_conn;
server 192.168.1.110:9000 weight=5 max_fails=3 fail_timeout=30s;
server 192.168.1.111:9000 weight=5 max_fails=3 fail_timeout=30s;
keepalive 32;
}
# 静态资源上游
upstream static_cluster {
server 192.168.1.110:80;
server 192.168.1.111:80;
}
server {
listen 80;
server_name example.com www.example.com;
# 静态文件直接由应用节点处理
location /static/ {
proxy_pass http://static_cluster;
proxy_cache_valid 200 7d;
expires 7d;
}
# PHP请求转发到PHP-FPM集群
location ~ \.php$ {
fastcgi_pass thinkphp_cluster;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# 超时设置
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
}
# 伪静态规则(ThinkPHP)
location / {
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?s=$1 last;
break;
}
}
# 健康检查
location /health {
access_log off;
return 200 "OK";
}
}
}
4.2 Keepalived高可用
在LB-1和LB-2上安装Keepalived:
sudo apt install keepalived -y
主节点配置(LB-1):
# /etc/keepalived/keepalived.conf
global_defs {
router_id NGINX_LB
}
vrrp_script chk_nginx {
script "/usr/local/bin/check_nginx.sh"
interval 2
weight -20
fall 3
rise 2
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass your_secret
}
virtual_ipaddress {
192.168.1.50/24
}
track_script {
chk_nginx
}
}
备用节点配置(LB-2):将state改为BACKUP,priority改为90。
健康检查脚本:
#!/bin/bash
# /usr/local/bin/check_nginx.sh
if ! killall -0 nginx; then
systemctl restart nginx
sleep 2
if ! killall -0 nginx; then
systemctl stop keepalived
fi
fi
五、ThinkPHP部署与优化
5.1 部署应用代码
# 所有应用节点执行
cd /var/www
# 克隆代码
git clone https://your-repo/thinkphp-app.git app
# 设置权限
chown -R www-data:www-data app
chmod -R 755 app
# 安装Composer依赖
cd app
composer install --no-dev --optimize-autoloader
# 生成运行时目录
mkdir -p runtime
chmod -R 777 runtime
5.2 PHP-FPM优化配置
; /etc/php/8.3/fpm/pool.d/www.conf
[www]
user = www-data
group = www-data
listen = 9000
listen.owner = www-data
listen.group = www-data
; 进程管理
pm = dynamic
pm.max_children = 80
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 40
pm.max_requests = 1000
pm.process_idle_timeout = 10s
; 性能优化
php_admin_value[opcache.enable] = 1
php_admin_value[opcache.memory_consumption] = 256
php_admin_value[opcache.max_accelerated_files] = 20000
php_admin_value[opcache.revalidate_freq] = 60
php_admin_value[opcache.validate_timestamps] = 0
; 超时设置
request_terminate_timeout = 300
5.3 ThinkPHP配置优化
// config/database.php - 数据库读写分离
return [
'default' => 'mysql',
'connections' => [
'mysql' => [
'type' => 'mysql',
'hostname' => '192.168.1.120',
'database' => 'thinkphp',
'username' => 'app_user',
'password' => 'YourPassword',
'hostport' => '3306',
'debug' => false,
// 主从配置
'deploy' => 1,
'rw_separate' => true,
'master_num' => 1,
'slave_no' => '',
'hosts' => [
// 读从库
['hostname' => '192.168.1.121', 'weight' => 1],
],
// 连接池
'break_reconnect' => true,
'max_connections' => 50,
],
],
];
// config/cache.php - Redis缓存
return [
'default' => 'redis',
'stores' => [
'redis' => [
'type' => 'redis',
'host' => '192.168.1.130',
'port' => 6379,
'password' => '',
'select' => 0,
'timeout' => 0,
'expire' => 3600,
'persistent' => true,
'prefix' => 'tp_cache:',
],
],
];
// config/session.php - Redis会话
return [
'type' => 'redis',
'store' => null,
'host' => '192.168.1.130',
'port' => 6379,
'password' => '',
'select' => 1,
'expire' => 7200,
'prefix' => 'tp_sess:',
];
六、数据库高可用
6.1 MariaDB主从配置
主库(DB-M):
# /etc/mysql/mariadb.conf.d/50-server.cnf
[mysqld]
server-id = 1
log_bin = mysql-bin
binlog_format = ROW
expire_logs_days = 7
max_binlog_size = 100M
# 半同步复制
plugin_load_add = semisync_master.so
rpl_semi_sync_master_enabled = 1
rpl_semi_sync_master_timeout = 1000
从库(DB-S):
# /etc/mysql/mariadb.conf.d/50-server.cnf
[mysqld]
server-id = 2
relay_log = relay-bin
log_bin = mysql-bin
read_only = 1
plugin_load_add = semisync_slave.so
rpl_semi_sync_slave_enabled = 1
6.2 创建复制用户
-- 在主库执行
CREATE USER 'repl_user'@'%' IDENTIFIED BY 'ReplPassword123!';
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'%';
FLUSH PRIVILEGES;
-- 查看主库状态
SHOW MASTER STATUS;
6.3 启动从库同步
-- 在从库执行
CHANGE MASTER TO
MASTER_HOST='192.168.1.120',
MASTER_USER='repl_user',
MASTER_PASSWORD='ReplPassword123!',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;
START SLAVE;
SHOW SLAVE STATUS\G
七、文件同步方案
7.1 使用NFS共享上传文件
存储服务器:
sudo apt install nfs-kernel-server -y
# 创建共享目录
mkdir -p /data/shared/uploads
chown -R nobody:nogroup /data/shared/uploads
# 配置NFS导出
echo "/data/shared/uploads 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)" >> /etc/exports
sudo exportfs -a
sudo systemctl restart nfs-kernel-server
应用节点挂载:
sudo apt install nfs-common -y
sudo mkdir -p /var/www/app/public/uploads
echo "192.168.1.120:/data/shared/uploads /var/www/app/public/uploads nfs defaults 0 0" >> /etc/fstab
sudo mount -a
7.2 使用lsyncd实时同步(替代方案)
sudo apt install lsyncd -y
# /etc/lsyncd/lsyncd.conf.lua
settings {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status",
inotifyMode = "CloseWrite",
maxProcesses = 10,
}
sync {
default.rsync,
source = "/var/www/app/public/uploads",
target = "192.168.1.111:/var/www/app/public/uploads",
delay = 1,
rsync = {
archive = true,
compress = true,
perms = true,
},
}
八、监控与告警
8.1 Prometheus + Grafana监控
监控关键指标:
| 指标 | 告警阈值 | 说明 |
|---|---|---|
| PHP-FPM进程数 | >80% max_children | 需要扩容 |
| 请求响应时间 | >3秒 | 性能瓶颈 |
| 错误率 | >1% | 应用异常 |
| MariaDB复制延迟 | >5秒 | 数据不一致 |
| 磁盘使用率 | >85% | 需要清理 |
| 内存使用率 | >90% | OOM风险 |
8.2 应用健康检查
// app/app/controller/Health.php
namespace app\controller;
class Health
{
public function index()
{
$checks = [
'database' => $this->checkDatabase(),
'redis' => $this->checkRedis(),
'disk' => $this->checkDisk(),
];
$healthy = !in_array(false, $checks);
return json([
'status' => $healthy ? 'OK' : 'FAIL',
'checks' => $checks,
'timestamp' => date('Y-m-d H:i:s'),
], $healthy ? 200 : 503);
}
private function checkDatabase(): bool
{
try {
\think\facade\Db::query('SELECT 1');
return true;
} catch (\Exception $e) {
return false;
}
}
private function checkRedis(): bool
{
try {
\think\facade\Cache::set('health_check', 1, 10);
return (bool)\think\facade\Cache::get('health_check');
} catch (\Exception $e) {
return false;
}
}
private function checkDisk(): bool
{
$free = disk_free_space('/var/www/app');
$total = disk_total_space('/var/www/app');
return ($free / $total) > 0.15;
}
}
九、自动化部署脚本
#!/bin/bash
# deploy.sh - 一键部署新版本到所有节点
# 用法: ./deploy.sh v1.2.3
VERSION=$1
NODES=("192.168.1.110" "192.168.1.111")
APP_DIR="/var/www/app"
BACKUP_DIR="/backup/deploy"
echo "=== 开始部署版本 $VERSION ==="
for node in "${NODES[@]}"; do
echo ">>> 部署到 $node ..."
# 创建备份
ssh root@$node "cd $APP_DIR && tar -czf $BACKUP_DIR/pre_$VERSION_$(date +%Y%m%d%H%M).tar.gz ."
# 拉取代码
ssh root@$node "cd $APP_DIR && git fetch origin && git checkout $VERSION && composer install --no-dev"
# 清理缓存
ssh root@$node "cd $APP_DIR && php think clear && php think optimize:route"
# 重启PHP-FPM
ssh root@$node "systemctl reload php8.3-fpm"
echo ">>> $node 部署完成"
done
echo "=== 所有节点部署完成 ==="
十、总结
| 组件 | 方案 | 高可用策略 |
|---|---|---|
| 负载均衡 | Nginx + Keepalived | VIP漂移,故障自动转移 |
| 应用层 | PHP-FPM多节点 | 水平扩展,滚动更新 |
| 数据库 | MariaDB主从 | 半同步复制,自动切换 |
| 会话 | Redis | 单点+持久化,Sentinel可选 |
| 文件 | NFS / lsyncd | 共享存储或实时同步 |
| 缓存 | Redis | 单实例或集群模式 |
关键原则:
1. 每一层都要有冗余,消除单点故障
2. 监控覆盖所有组件,告警及时响应
3. 自动化部署,减少人为错误
4. 定期演练故障恢复流程
注:本文基于ThinkPHP 8.x、PHP 8.3、Debian 12编写,请根据实际环境调整配置。