一、架构概览
10.0.0.4 - LB服务器(Haproxy实现四层负载,四层负载分配的是用户连接)
172.16.1.5 - LB01服务器(nginx实现七层负载,七层负载分配的是用户的多个请求)
172.16.1.6 - LB02服务器(nginx实现七层负载)
172.16.1.7 - web01(Nginx + php-fpm)
172.16.1.9 - web02(Nginx + php-fpm)
172.16.1.51 - MySQL服务器
172.16.1.31 - NFS服务器
环境:CentOS7虚拟机
二、NFS服务器配置
在.31服务器上:
1.安装NFS服务器
yum install -y nfs-utils rpcbind
2.创建wordpress共享目录
mkdir -p /data/wordpress/wp-content/
mkdir -p /data/wordpress/uploads/
3.设置权限
chown -R nfsnobody.nfsnobody /data/wordpress/wp-content
chown -R nfsnobody.nfsnobody /data/wordpress/uploads
4.配置NFS共享文件
位置:/etc/exports
添加:
/data/wordpress/wp-content 172.16.1.0/24(rw,sync,all_squash)
5.启动服务并配置开机自启动
systemctl start nfs-server
systemctl enable nfs-server
systemctl start rpcbind
systemctl enable rpcbind
6.验证共享目录
showmount -e localhost
三、MySQL服务器配置
在172.16.1.51中
1.安装mariadb
yum install -y mariadb-server mariadb
2.启动mariadb
systemctl start mariadb
systemctl enable mariadb
3.运行安全配置脚本
mysql_secure_installation
4.创建wordpress数据库和用户
mysql -u root -p
输入root密码进入数据库
创建数据库:
create database if not exists wordpress default character set utf8mb4 collate utf8mb4_unicode_ci;
创建wordpress用户并授权
createuser 'wpuser'@'172.16.1.%' identified by 'TJCKD1ZNb';
grant all privileges on wordpress.* to 'wpuser'@'172.16.1.%';
flush privileges;#刷新权限
验证用户创建及其权限
select user, host from mysql.user where user = 'wpuser';
四、web01服务器配置
在172.16.1.7中:
1.安装基础软件
安装epel仓库
yum install -y epel-release
安装nginx
yum install -y nginx
安装Remi仓库获取php 7.4
yum install -y https://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum-config-manager --enable remi-php74
2.安装php及其相关拓展
yum install -y php php-fpm php-mysqlnd php-gd php-mbstring php-xml \
php-curl php-zip php-json php-opcache
3.安装nfs客户端
yum install -y nfs-utils
4.配置php-fpm
配置文件:
/etc/php-fpm.d/www.conf
备份配置文件:
cp /etc/php-fpm.d/www.conf /etc/php-fpm.d/www.conf.bak
编辑配置文件:
vim /etc/php-fpm.d/www.conf
改成:
user = nginx
group = nginx
5.创建php会话目录并设置权限
mkdir -p /var/lib/php/session
chown -R nginx.nginx /var/lib/php/session
6.启动php-fpm
systemctl start php-fpm
systemctl enable php-fpm
systemctl status php-fpm
7.配置NFS挂载
创建挂载点:
mkdir -p /var/www/html/wordpress/wp-content
挂载:
mount -t nfs 172.16.1.31:/data/wordpress/wp-content /var/www/html/wordpress/wp-content
验证挂载:
df -h
配置开机自动挂载:
vim /etc/fstab
键入:
172.16.1.31:/data/wordpress/wp-content /var/www/html/wordpress/wp-content nfs defaults_netdev 0 0
设置wordpress的目录权限:
chown -R nginx.nginx /var/www/html/wordpress
8.配置nginx
配置文件:/etc/nginx/nginx.conf
nginx.conf文件里面包含了conf.d/文件夹,所以你可以在conf.d里面新建***.conf文件即可编写配置
备份原始配置文件:
cp /etc/nginx/nginx.conf /etc/nginx.conf.bak
创建wordpress配置文件:
touch /etc/nginx/conf.d/wordpress.conf
vim !$
键入:
server{
listen 80;
server_name www.wp.com;
root /var/www/html/wordpress/
index index.html index.htm index.php;
# WordPress重写规则
location / {
try_files $uri $uri/ /index.php?$args;
}
# 禁止访问敏感文件
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
location ~* /(?:uploads|files)/.*\.php$ {
deny all;
}
# 缓存静态文件
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 30d;
add_header Cache-Control "public, immutable";
log_not_found off;
}
# PHP处理
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# 增加PHP超时时间
fastcgi_read_timeout 300;
}
# 禁止访问特定文件
location ~* \.(engine|inc|install|make|module|profile|po|sh|.*sql|theme|twig|tpl(\.php)?|xtmpl|yml)(~|\.sw[op]|\.bak|\.orig|\.save)?$|\/(\.(?!well-known).*|Entries.*|Repository|Root|Tag|Template|composer\.(json|lock))$|\/code-style\.pl$|\.(log|svn|git)|maintenance\.html|README\.html {
deny all;
access_log off;
log_not_found off;
}
# 访问日志
access_log /var/log/nginx/wordpress_access.log;
error_log /var/log/nginx/wordpress_error.log;
}
测试配置文件语法:
nginx -t
启动nginx服务:
systemctl start nginx
systemctl enable nginx
五、部署wordpress
1.下载wordpress并解压
去家目录:
cd
wget https://wordpress.org/latest.tar.gz
解压:
tar -zxvf latest.tar.gz
然后会生成一个wordpress文件夹,里面有wp-admin/ wp-content wp-????/
2.复制wordpress文件夹
复制wordpress文件夹下的内容到/var/www/html/wordpress/下
cp -r wordpress/* /var/www/html/wordpress/
然后原来的wp-content(空)会被新生成的wp-content(里面有index.php plugins themes)给覆盖
3.配置wordpress配置文件
配置文件:/var/www/html/wordpress/wp-config.php
vim !$
编辑:
//MySQL设置
define('DB_NAME','');
define('DB_USER','');
define('DB_PASSWORD','');
define('DB_HOST','');
define('DB_CHARSET','');
//从NFS服务器加载wp-content
define('WP_CONTENT_DIR','/var/www/html/wordpress/wp-content');
define('WP_CONTENT_URL','http://' . $_SERVER['HTTP_HOST'] . '/wp-content');
4.设置文件权限
chown -R nginx.nginx /var/www/html/wordpress
并保证文件夹的权限是755,文件的权限是644
5.重启服务
systemctl restart nginx
systemctl restart php-fpm
六、部署web02服务器
在完成了前面四步的时候,你就可以构造出web01,NFS,mysql这个小型服务器架构了,接下来就是部署web02,把web02给加入进去,实现一个小型的web服务器集群。
1、在web02(10.0.0.9)上的配置
1.1 安装基础软件(同web01)
yum install -y epel-release
yum install -y nginx
# 安装Remi仓库和PHP 7.4
yum install -y https://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum-config-manager --enable remi-php74
# 安装PHP及其扩展
yum install -y php php-fpm php-mysqlnd php-gd php-mbstring php-xml \
php-curl php-zip php-json php-opcache
# 安装NFS客户端
yum install -y nfs-utils
1.2 配置PHP-FPM(同web01)
# 备份并编辑配置文件
cp /etc/php-fpm.d/www.conf /etc/php-fpm.d/www.conf.bak
vim /etc/php-fpm.d/www.conf
修改:
user = nginx
group = nginx
*********这里我见建议是直接拷贝web01的/etc/php-fpm.d/www.conf文件下来***************
*********因为默认的配置文件的话没有 listen = /var/run/php/php-fpm.socket 这一行*****
*********否则到最后访问网站会出现502错误********************************************
# 创建会话目录
mkdir -p /var/lib/php/session
chown -R nginx.nginx /var/lib/php/session
# 启动php-fpm
systemctl start php-fpm
systemctl enable php-fpm
3. 配置NFS挂载
# 创建网站目录
mkdir -p /var/www/html/wordpress
# 测试NFS连接
showmount -e 172.16.1.31
# 挂载NFS共享(注意:只挂载wp-content目录)
mkdir -p /var/www/html/wordpress/wp-content
mount -t nfs 172.16.1.31:/data/wordpress/wp-content /var/www/html/wordpress/wp-content
# 验证挂载
df -h | grep nfs
# 配置开机自动挂载
echo "172.16.1.31:/data/wordpress/wp-content /var/www/html/wordpress/wp-content nfs defaults,_netdev 0 0" >> /etc/fstab
4. 关键步骤:从web01同步WordPress核心文件
# 方法1:使用rsync从web01同步(推荐)
# 确保web01和web02之间可以ssh连接
rsync -avz root@172.16.1.7:/var/www/html/wordpress/ /var/www/html/wordpress/ --exclude=wp-content
# 或者方法2:手动复制(如果不能用rsync)
# 在web01上打包WordPress核心文件(排除wp-content)
# ssh到web01执行:
# cd /var/www/html
# tar --exclude=wordpress/wp-content -czf wordpress-core.tar.gz wordpress/
# scp wordpress-core.tar.gz root@10.0.0.9:/root/
# 然后在web02上:
# tar -xzf /root/wordpress-core.tar.gz -C /var/www/html/
5. 配置wp-config.php(从web01复制)
# 从web01复制配置文件
scp root@172.16.1.7:/var/www/html/wordpress/wp-config.php /var/www/html/wordpress/
# 或者手动创建(内容与web01相同)
vim /var/www/html/wordpress/wp-config.php
确保内容包含:
define('DB_NAME', 'wordpress');
define('DB_USER', 'wpuser');
define('DB_PASSWORD', 'TJCKD1ZNb');
define('DB_HOST', '172.16.1.51'); # MySQL服务器IP
define('DB_CHARSET', 'utf8mb4');
define('WP_CONTENT_DIR', '/var/www/html/wordpress/wp-content');
define('WP_CONTENT_URL', 'http://' . $_SERVER['HTTP_HOST'] . '/wp-content');
6. 设置权限
chown -R nginx.nginx /var/www/html/wordpress
find /var/www/html/wordpress -type d -exec chmod 755 {} \;
find /var/www/html/wordpress -type f -exec chmod 644 {} \;
7. 配置Nginx
# 创建配置文件
vim /etc/nginx/conf.d/wordpress.conf
使用与web01完全相同的配置:
server {
listen 80;
server_name www.wp.com; # 与web01相同的域名
root /var/www/html/wordpress/
index index.html index.htm index.php
# 其他配置与web01完全相同...
# 复制web01的nginx配置到这里
}
测试并启动:
nginx -t
systemctl start nginx
systemctl enable nginx
四、验证配置
1. 测试数据库连接
# 在web02上测试
php -r "
\$conn = new mysqli('172.16.1.51', 'wpuser', 'TJCKD1ZNb', 'wordpress');
if (\$conn->connect_error) {
die('连接失败: ' . \$conn->connect_error);
} else {
echo '数据库连接成功!';
\$conn->close();
}
"
2. 测试文件同步
# 在web02上创建测试文件
echo "Web02 test at $(date)" > /var/www/html/wordpress/wp-content/web02_test.txt
# 在web01上检查(ssh到web01)
# cat /var/www/html/wordpress/wp-content/web02_test.txt
3. 测试WordPress访问
# 创建测试PHP文件
echo "<?php
require_once('/var/www/html/wordpress/wp-load.php');
echo 'WordPress加载成功!用户名:' . wp_get_current_user()->user_login;
?>" > /var/www/html/wordpress/test_wp.php
# 通过浏览器访问 http://10.0.0.9/test_wp.php
# 完成后删除测试文件
rm -f /var/www/html/wordpress/test_wp.php
七、部署LB01服务器
在10.0.0.5中:
1. 下载nginx
yum install -y epel-release
yum install -y nginx
2. 配置文件
vim /etc/nginx/conf.d/load-balance.conf
写入配置文件:
upstream webs{
server 172.16.1.7:80;
server 172.16.1.9:80;
# nginx健康状态检测需要用到nginx_upstream_check_module
}
server{
listen 80;
server_name www.wp.cc;
access_log /var/log/nginx/lb-access.log main;
location / {
# 反向代理设置
proxy_pass http://webs;
# 重要的代理头部
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_connect_timeout 5s;
proxy_send_timeout 10s;
proxy_read_timeout 10s;
# 缓冲设置
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
# 其他优化
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
3. 启动nginx并设置开机自启动
nginx -t
systemctl start nginx
systemctl enable nginx
八、部署LB02服务器
1. 下载nginx
yum install -y epel-release
yum install -y nginx
2. 拷贝LB01的配置文件
scp 172.16.1.5:/etc/nginx/conf.d/load-balance.conf /etc/nginx/conf.d/
3. 启动nginx并设置开机自启动
nginx -t
systemctl start nginx
systemctl enable nginx
九、部署LB服务器
1. 下载Haproxy
yum install -y haproxy
2. 配置文件
位置:/etc/haproxy/haproxy.cfg
vim /etc/haproxy/haproxy.cfg
写入配置文件:
global
log /dev/log local0
maxconn 100000
user haproxy
group haproxy
daemon
defaults
mode tcp
timeout connect 5s
timeout client 30s
timeout server 30s
log global
frontend tcp_front
bind *:80
default_backend tcp_back
backend tcp_back
balance roundrobin
server lb01 172.16.1.5:80 check maxconn 10000
server lb02 172.16.1.6:80 check maxconn 10000
listen stats
bind *:1936
mode http
stats enable
stats uri /
stats hide-version
stats auth admin:password
3. 启动HAProxy
systemctl start haproxy
systemctl enable haproxy
十、会话一致问题
由于web01和web02是独立的,用户登录状态不会自动同步。
解决方案:
方案A:使用数据库存储session(推荐)
# 在web01和web02上都修改
vim /etc/php-fpm.d/www.conf
# 添加
php_value[session.save_handler] = redis
php_value[session.save_path] = "tcp://172.16.1.51:6379"
# 安装Redis服务器(可以在MySQL服务器或单独服务器上)
方案B:使用NFS存储session
# 在NFS服务器上创建共享目录
mkdir -p /data/php-session
chown nfsnobody.nfsnobody /data/php-session
# 在/etc/exports中添加
/data/php-session 172.16.1.0/24(rw,sync,all_squash)
# 在web01和web02上挂载并修改php.ini
mkdir -p /var/lib/php/session
mount -t nfs 172.16.1.31:/data/php-session /var/lib/php/session
vim /etc/php.ini
# 修改
session.save_path = "/var/lib/php/session"
十一、nginx健康状态检测
1. 安装健康检查模块
在172.16.1.5(LB01)和172.16.1.6(LB02)上执行:
1.1 查看nginx版本:
nginx -v
1.2 下载nginx源码和模块:
# 1. 安装编译工具
yum install -y gcc make pcre-devel zlib-devel openssl-devel git
# 2. 进入源码目录
cd /usr/local/src
# 3. 下载Nginx源码(版本要匹配)
wget http://nginx.org/download/nginx-1.20.1.tar.gz
tar -zxvf nginx-1.20.1.tar.gz
# 4. 下载健康检查模块
# 使用Gitee镜像
git clone https://gitee.com/mirrors/nginx_upstream_check_module.git
1.3 打补丁并编译:
# 1. 进入Nginx源码目录
cd /usr/local/src/nginx-1.20.1
# 2. 打补丁(重要!)
patch -p1 < /usr/local/src/nginx_upstream_check_module/check_1.20.1+.patch
# 如果报错,试试其他补丁文件,如:check_1.16.0+.patch
# 3. 查看当前编译参数
nginx -V 2>&1 | grep 'configure arguments'
# 4. 重新配置(添加健康检查模块)
./configure \
--prefix=/usr/share/nginx \
--sbin-path=/usr/sbin/nginx \
--modules-path=/usr/lib64/nginx/modules \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/run/nginx.pid \
--lock-path=/run/lock/subsys/nginx \
--user=nginx \
--group=nginx \
--with-compat \
--with-file-aio \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_realip_module \
--with-http_gzip_static_module \
--with-http_v2_module \
--with-pcre \
--with-pcre-jit \
--with-threads \
--add-module=/usr/local/src/nginx_upstream_check_module
# 5. 编译
make
# 6. 备份旧Nginx
cp /usr/sbin/nginx /usr/sbin/nginx.backup
# 7. 停止Nginx
systemctl stop nginx
# 8. 安装新编译的Nginx
cp objs/nginx /usr/sbin/nginx
# 9. 验证模块
nginx -V 2>&1 | grep check_module
# 应该看到:--add-module=/usr/local/src/nginx_upstream_check_module
2. 配置健康检查
2.1 修改nginx配置
# 编辑Nginx配置文件
vim /etc/nginx/conf.d/load-balance.conf
# 在upstream模块中添加健康检查配置:
upstream wordpress_backend {
# 后端服务器
server 172.16.1.7:80;
server 172.16.1.9:80;
# 健康检查配置(核心!)
check interval=3000 rise=2 fall=3 timeout=2000 type=http;
check_http_send "HEAD / HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
# 在server模块中添加健康检查状态页面:
server {
listen 80;
server_name www.wp.com;
root /var/www/html/wordpress/;
index index.php index.html;
# WordPress重写规则
location / {
try_files $uri $uri/ /index.php?$args;
}
# PHP处理
location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# 代理到后端服务器
location @proxy {
proxy_pass http://wordpress_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# 健康检查状态页面(重要!)
location /status {
check_status;
access_log off;
# 只允许内网访问
allow 172.16.1.0/24;
deny all;
}
}
3. 测试并重启nginx
# 1. 测试配置文件
nginx -t
# 应该输出:nginx: configuration file /etc/nginx/nginx.conf test is successful
# 2. 启动Nginx
systemctl start nginx
# 3. 查看状态
systemctl status nginx
4. 测试健康检查功能
# 1. 查看状态页面
curl http://172.16.1.5/status
# 应该看到表格,显示服务器状态
# 2. 查看JSON格式状态
curl http://172.16.1.5/status?format=json
# 看到JSON数据
# 3. 测试后端服务器
curl -I http://172.16.1.7
curl -I http://172.16.1.9
十二、架构的数据流向
让我们从客户端点击"刷新"按钮开始,一步一步追踪整个数据流向。这就像一部网络世界的"漫游记"。
一、完整的数据旅程
第一阶段:客户端浏览器
用户 → 浏览器 → 操作系统网络栈
- 用户动作:用户在浏览器中按F5或点击刷新按钮
- 浏览器行为:
- 浏览器检查本地DNS缓存中是否有
www.wp.com的解析记录 - 如果有缓存且未过期,直接使用缓存的IP;否则进行DNS查询
- DNS解析:
# 假设你的DNS将 www.wp.com 解析到 172.16.1.4
浏览器 → 本地DNS缓存 → ISP DNS → 递归查询 → 权威DNS
↓
返回: www.wp.com = 172.16.1.4
第二阶段:到达四层负载均衡器 (HAProxy, 172.16.1.4)
浏览器 → HAProxy (TCP层处理)
- TCP握手开始:
# 三次握手
浏览器: SYN → HAProxy(172.16.1.4:80)
HAProxy: SYN-ACK → 浏览器
浏览器: ACK → HAProxy
# 此时TCP连接建立完成
- HAProxy内部处理:
# HAProxy收到SYN包时的处理流程
收到SYN包 → 检查frontend配置 → 选择backend → 选择后端服务器
↓
1. 查看 /etc/haproxy/haproxy.cfg
2. 匹配到 frontend http_frontend (监听 *:80)
3. 找到对应的 backend http_backend
4. 根据负载均衡算法选择后端:
- 如果是 roundrobin: 轮流选择 172.16.1.5 或 172.16.1.6
- 如果是 leastconn: 选择当前连接数最少的那台
5. 假设选择了 172.16.1.6
- HAProxy建立到后端的连接:
# HAProxy与后端建立独立TCP连接
HAProxy: SYN → 172.16.1.6:80
172.16.1.6: SYN-ACK → HAProxy
HAProxy: ACK → 172.16.1.6
# 现在有两个TCP连接:
# 连接A: 浏览器 ↔ HAProxy
# 连接B: HAProxy ↔ 172.16.1.6
第三阶段:七层负载均衡器 (Nginx, 172.16.1.6)
HAProxy → Nginx (HTTP层开始)
- Nginx接收请求:
# Nginx的worker进程接收连接
# 假设使用epoll事件驱动模型
事件循环: epoll_wait() 检测到新连接
→ 调用 accept() 接受连接
→ 创建连接结构体 ngx_connection_t
→ 开始接收HTTP请求数据
- 解析HTTP请求:
# Nginx解析浏览器发送的HTTP请求
接收到的原始数据:
GET / HTTP/1.1
Host: www.wp.com
User-Agent: Mozilla/5.0...
Accept: text/html,application/xhtml+xml...
Cookie: wordpress_logged_in_xxx=...
Connection: keep-alive
- Nginx处理逻辑:
# Nginx根据配置文件处理
1. 匹配 server_name: www.wp.com
2. 找到对应的 location /
3. 查看 upstream 配置:
upstream wordpress_backend {
server 172.16.1.7:80;
server 172.16.1.9:80;
}
4. 选择后端Web服务器(假设选择 172.16.1.7)
5. 添加代理头部:
X-Real-IP: <原始客户端IP>
X-Forwarded-For: <原始客户端IP>
X-Forwarded-Proto: http
- 建立到Web服务器的连接:
bash # Nginx与Web服务器建立第三个TCP连接 Nginx: SYN → 172.16.1.7:80 172.16.1.7: SYN-ACK → Nginx Nginx: ACK → 172.16.1.7 # 现在有三个TCP连接: # 连接A: 浏览器 ↔ HAProxy # 连接B: HAProxy ↔ Nginx # 连接C: Nginx ↔ Web服务器
第四阶段:Web服务器 (172.16.1.7)
Nginx → Web服务器 → PHP-FPM
- Web服务器接收请求:
# Nginx on 172.16.1.7 接收请求 1. 接收完整的HTTP请求 2. 解析头部,看到 Host: www.wp.com 3. 匹配到 wordpress 配置 4. 根据 location ~ \.php$ 转发给PHP-FPM - PHP-FPM处理:
# Nginx通过FastCGI协议与PHP-FPM通信 1. Nginx将HTTP请求转换为FastCGI请求: SCRIPT_FILENAME: /var/www/html/wordpress/index.php REQUEST_METHOD: GET QUERY_STRING: (空) DOCUMENT_ROOT: /var/www/html/wordpress REMOTE_ADDR: <原始客户端IP> 2. 通过Unix socket发送到PHP-FPM: /var/run/php-fpm/php-fpm.sock 3. PHP-FPM worker进程处理: - 从空闲worker池中分配一个worker - worker执行 /var/www/html/wordpress/index.php - WordPress执行:
# WordPress的index.php执行流程 1. 加载 wp-config.php 2. 读取数据库配置: DB_HOST=172.16.1.51 3. 连接MySQL数据库 4. 执行SQL查询获取页面内容 5. 读取NFS共享的主题文件 6. 生成HTML页面 - 数据库访问:
# WordPress连接MySQL的过程 PHP-FPM worker → TCP连接 → 172.16.1.51:3306 ↓ 认证: wpuser/TJCKD1ZNb 查询: SELECT * FROM wp_posts... ↓ MySQL返回查询结果 - NFS文件访问:
bash # 读取主题文件的过程 PHP-FPM: stat("/var/www/html/wordpress/wp-content/themes/xxx/style.css") ↓ 内核NFS客户端: RPC调用 ↓ 网络: 172.16.1.7 → 172.16.1.31:2049 ↓ NFS服务器: 读取磁盘文件 ↓ 返回文件内容
第五阶段:响应返回路径
WordPress → PHP-FPM → Nginx → HAProxy → 浏览器
- 生成响应:
# PHP执行完成,返回HTML PHP-FPM: 生成完整的HTML页面 → 通过FastCGI返回给Nginx → Nginx接收响应数据 - Nginx处理响应:
# Nginx可能进行的优化 1. Gzip压缩(如果配置了) 2. 添加响应头: Content-Type: text/html; charset=UTF-8 Server: nginx X-Powered-By: PHP/7.4 3. 可能写入缓存(如果配置了) 4. 发送响应给HAProxy - HAProxy转发响应:
# HAProxy只是转发TCP数据包 接收Nginx的TCP数据包 → 转发给浏览器 不解析HTTP内容,只处理TCP层 - 浏览器接收响应:
# 浏览器渲染页面 1. 接收HTTP响应头 2. 接收HTML内容 3. 解析HTML,发现需要CSS/JS/图片 4. 对每个资源重复上述过程(可能并行) - TCP连接关闭:
bash # 根据HTTP keep-alive设置 # 如果是HTTP/1.1 keep-alive: 连接保持,等待下一个请求 # 如果是短连接: 浏览器: FIN → HAProxy → Nginx → Web服务器 四向挥手,关闭所有连接
二、关键路径总结
物理路径:
客户端
↓ (HTTP/TCP)
四层LB: HAProxy (172.16.1.4:80)
↓ (纯TCP转发)
七层LB: Nginx (172.16.1.6:80)
↓ (HTTP代理)
Web服务器: Nginx + PHP-FPM (172.16.1.7:80)
↓ (FastCGI)
PHP-FPM进程
↓ (MySQL TCP连接)
数据库: MariaDB (172.16.1.51:3306)
↓ (NFS/RPC)
文件存储: NFS (172.16.1.31:2049)
协议栈变化:
浏览器端: HTTP over TCP
↓
HAProxy: 只看到TCP层
↓
Nginx(LB): 解析HTTP,重新封装
↓
Web服务器: HTTP → FastCGI
↓
PHP-FPM: 执行PHP
↓
MySQL: MySQL协议 over TCP
↓
NFS: RPC over TCP
三、为什么四层+七层架构能解决高并发问题?
1. 连接管理对比
传统单层架构(假设10万并发):
浏览器(10万连接) → Nginx七层LB(10万连接) → Web服务器
问题:
- Nginx需要维护10万个文件描述符
- 需要10万个本地端口(但临时端口只有~28000个)
- 每个连接都需要HTTP解析,CPU压力大
四层+七层架构:
浏览器(10万连接) → HAProxy四层(10万连接) → Nginx集群(每个2.5万连接) → Web服务器
优势:
- HAProxy: 只处理TCP,10万连接轻松应对
- 每个Nginx: 只处理部分连接(如2.5万),在合理范围内
- 端口复用: HAProxy可以用少量端口与Nginx通信
2. 端口限制的数学解释
# Linux临时端口范围
cat /proc/sys/net/ipv4/ip_local_port_range
# 输出: 32768 60999
# 可用端口数: 60999 - 32768 + 1 = 28232
# 单Nginx场景:
# 每个客户端连接需要一个本地端口
# 最大并发连接数 ≈ 28232
# 超过这个数就会出现"端口耗尽"
# 四层+七层场景:
# HAProxy到Nginx的连接可以复用
# HAProxy端口使用: 100个连接可能只用几个端口
# Nginx集群: 每个实例连接数控制在2.8万以内
3. 性能优化点
HAProxy层优化:
# 内核bypass技术
# HAProxy可以直接从网卡DMA读取数据,减少拷贝
# 使用SO_REUSEPORT允许多进程监听同一端口
# 零拷贝技术转发TCP数据包
Nginx层优化:
# 可以专注于HTTP优化
# 启用缓存:proxy_cache
# 启用压缩:gzip
# 连接池:keepalive到后端
四、一次完整请求的时间线(假设所有缓存都未命中)
时间 事件
----- --------------------------------------------------
0ms 用户点击刷新
1ms DNS解析完成(本地无缓存)
2ms TCP握手开始
3ms TCP握手完成
4ms HTTP请求发送
5ms 请求到达HAProxy
6ms HAProxy建立到Nginx的连接
7ms 请求到达Nginx七层LB
8ms Nginx解析HTTP头部
9ms Nginx建立到Web服务器的连接
10ms 请求到达Web服务器
11ms Web服务器转发给PHP-FPM
12ms PHP-FPM开始执行index.php
15ms WordPress连接数据库
20ms 数据库返回查询结果
25ms WordPress读取NFS文件
30ms PHP执行完成
31ms Web服务器发送响应
32ms Nginx接收响应
33ms Nginx发送响应给HAProxy
34ms HAProxy转发给浏览器
35ms 浏览器开始接收HTML
40ms 浏览器解析HTML,发起CSS/JS请求
... 并行加载所有资源
500ms 页面完全加载完成
五、故障排查视角
如果页面加载缓慢,可以从后往前排查:
- 查看浏览器开发者工具:哪个阶段耗时?
- 检查HAProxy日志:
tail -f /var/log/haproxy.log - 查看Nginx访问日志:
tail -f /var/log/nginx/access.log - 检查PHP-FPM慢日志:查看是否有慢查询
- 监控MySQL慢查询:
mysqldumpslow /var/log/mysql-slow.log - 检查NFS性能:
nfsstat -c
六、这种架构的核心思想
你可以把这个架构想象成一个高效的物流系统:
- HAProxy(四层):像高速公路收费站
- 只关心有多少辆车(连接),不关心车里装什么(HTTP内容)
- 快速分流到不同车道(Nginx实例)
- 处理能力:每分钟可通过10万辆车
- Nginx集群(七层):像物流分拣中心
- 拆开包裹查看内容(解析HTTP)
- 根据地址分拣到不同配送区域(Web服务器)
- 还能打包优化(Gzip压缩)
- Web服务器:像配送站
- 处理具体的配送任务(执行PHP)
- 数据库/NFS:像仓库
- 提供货物(数据/文件)
这种分层设计让每个组件专注于自己最擅长的工作,通过分工合作实现整体高性能。
Comments NOTHING