签入版本

This commit is contained in:
小蚂蚁云
2026-10-25 17:24:27 +08:00
parent 48911cc08f
commit fdbeae092a
1010 changed files with 30682 additions and 95274 deletions
+36 -139
View File
@@ -1,159 +1,56 @@
# 11.7 性能调优
:::tip 概述
本节从 PHP、缓存、数据库、前端四个维度提供性能调优建议。
调优顺序:**先观测、再定位、后调参**。可观测面有三层:Prometheus 指标(宏观)、服务监控页(主机)、SQL debug 日志(微观)。本页给出常见瓶颈与对应手段。
:::
## PHP 层
## 调优顺序
### OPcache(生产环境必须)
```ini
; =============================================================================
; php.ini — OPcache 字节码缓存配置
; =============================================================================
; OPcache 将 PHP 脚本编译为字节码并缓存在内存中,避免每次请求重复编译
; 启用后可提升 50%-80% 的 PHP 性能
; =============================================================================
opcache.enable = 1 ; 启用 OPcache(0=关闭,1=启用)
opcache.memory_consumption = 256 ; OPcache 共享内存大小(MB),按项目规模调整
opcache.interned_strings_buffer = 16 ; 驻留字符串内存(MB),减少重复字符串存储
opcache.max_accelerated_files = 10000 ; 最大缓存文件数(需大于项目 PHP 文件总数)
opcache.validate_timestamps = 0 ; 不检查文件修改时间(性能最优,更新代码后需重启 PHP-FPM)
opcache.save_comments = 1 ; 保留注释(ThinkPHP 注解依赖此配置)
```text
① /metrics 看哪类路由耗时高、错误率高
② 服务监控页看主机资源(CPU/内存/goroutine)
③ SQL debug 定位慢查询
④ 按瓶颈类型施加对应手段
⑤ 复测指标
```
:::warning OPcache 注意事项
`validate_timestamps = 0` 时,更新代码后必须重启 PHP-FPM 或手动清除 OPcache,否则不会生效。
:::
### PHP-FPM 进程池
```ini
; =============================================================================
; PHP-FPM 进程池配置
; =============================================================================
; 配置路径:/etc/php/8.2/fpm/pool.d/www.conf
; 根据服务器内存和并发量调整参数
; =============================================================================
pm = dynamic ; 动态进程管理(推荐)
pm.max_children = 50 ; 最大子进程数(每个约 30-50MB,根据内存调整)
pm.start_servers = 5 ; 启动时的进程数
pm.min_spare_servers = 5 ; 最小空闲进程(低于此值自动创建)
pm.max_spare_servers = 35 ; 最大空闲进程(高于此值自动销毁)
pm.max_requests = 500 ; 单进程最大请求数(达到后重启,防内存泄漏)
```
### Composer 优化
```bash
# 生产环境安装依赖
# --no-dev → 排除开发依赖(symfony/var-dumper、think-trace 等)
# --optimize-autoloader → 优化自动加载器(生成 classmap,减少文件查找)
composer install --no-dev --optimize-autoloader
```
## 缓存层
### 使用 Redis
```ini
; .env — Redis 缓存配置
[CACHE]
DRIVER = redis ; 缓存驱动改为 redis(默认为 file)
REDIS_HOST = 127.0.0.1 ; Redis 服务器地址
REDIS_PORT = 6379 ; Redis 端口
REDIS_PASSWORD = your_redis_password ; Redis 密码
```
:::tip 缓存效果
DictService 和 ParamService 采用两级缓存(请求级 + 持久缓存),使用 Redis 后:
- 字典查询:首次查库 + 写入 Redis,后续直接读缓存(1小时过期)
- 参数查询:同上
- 减少 80%+ 的数据库查询
:::
## 数据库层
### 索引优化
| 症状 | 手段 |
|---|---|
| 慢查询 | 高频列补索引(idx_{表}_{列});核对是否 LIKE 前置通配 |
| 连接耗尽 | 调 database 连接池(maxOpenConns/maxIdleConns/connMaxLifetime),核对应用与 MySQL 两侧 |
| 大分页深翻 | 避免大 offset;业务上限 pageSize 500 已兜底 |
| 频繁字典查询 | 字典缓存已内置;确认未被频繁 Refresh 打穿 |
```sql
-- =============================================================================
-- 为常用查询字段添加索引(提升查询速度)
-- =============================================================================
-- 索引原理:类似书的目录,数据库通过索引快速定位数据行,避免全表扫描
-- 注意:索引会占用额外存储空间,且降低写入速度,只在高频查询字段上创建
-- =============================================================================
## 应用层
-- 用户表:用户名登录查询、租户隔离查询
ALTER TABLE think_user ADD INDEX idx_username (username);
ALTER TABLE think_user ADD INDEX idx_tenant_id (tenant_id);
| 症状 | 手段 |
|---|---|
| goroutine 突增 | 监控页观察趋势;排查泄漏(未收尾的 goroutine、阻塞 channel) |
| 内存增长 | 大查询/导出是否一次载入过大结果集(导出走流式/分批) |
| 接口整体变慢 | 看限流是否误伤、日志是否过度(logQuery 巨量) |
| 日志盘涨 | 校准 job.logRetentionDays;zap 轮转配置 |
-- 文章表:状态筛选、分类筛选
ALTER TABLE think_article ADD INDEX idx_status (status);
ALTER TABLE think_article ADD INDEX idx_category_id (category_id);
## 缓存层
-- 操作日志表:按时间范围查询(最频繁的查询模式)
ALTER TABLE think_operation_log ADD INDEX idx_create_time (create_time);
```
- Redis 命中率低 → 检查键 TTL 与失效策略
- 降级内存模式 → 修复 Redis(多实例下内存模式语义退化)
- 大 key 排查 → Info memory 分区 + 键空间抽样
### 慢查询日志
## 限流与入口
```ini
; MySQL my.cnf — 慢查询日志配置
; 配置路径:/etc/mysql/my.cnf 或 /etc/my.cnf
; 生效命令:sudo systemctl restart mysql
- 公网收敛 rateLimit.limit(默认 120/min/IP 已可用)
- Nginx 层配连接/速率限制作为第一道闸
- 上传大小 maxSize 与 client_max_body_size 对齐,防大文件打内存
slow_query_log = 1 ; 启用慢查询日志
slow_query_log_file = /var/log/mysql/slow.log ; 日志文件路径
long_query_time = 2 ; 超过 2 秒的查询记录为慢查询
```
## 容量规划参考
### 连接池
- 无状态应用可横向扩(多实例共享 Redis/MySQL;限流计数 Redis 共享)
- 读压力大优先加只读库/缓存,而非盲目加应用实例
- 监控告警:按 route 维度配 P95 耗时与错误率阈值
高并发场景建议配置持久连接:
## 相关
```ini
; php.ini — 使用 Unix Socket 连接 MySQL(比 TCP 更快)
; 前提:PHP-FPM 和 MySQL 在同一台服务器上
pdo_mysql.default_socket = /var/run/mysqld/mysqld.sock
```
## 前端层
### Gzip 压缩
```nginx
# Nginx Gzip 压缩配置(添加到 http 或 server 块)
gzip on; ; 启用 Gzip 压缩
gzip_types text/plain text/css application/json application/javascript text/xml; ; 需要压缩的 MIME 类型
gzip_min_length 1024; ; 小于 1KB 的响应不压缩(压缩收益低)
```
### 静态资源缓存
```nginx
# 静态资源浏览器缓存配置(添加到 server 块)
# Vite 构建的文件名包含 content hash,可放心设置长期缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 30d; ; 缓存 30 天
add_header Cache-Control "public, immutable"; ; 公共缓存,内容不变
}
```
### CDN 加速
将静态资源(JS/CSS/图片)部署到 CDN,减轻服务器压力。
## 性能检查清单
| 检查项 | 生产环境 | 开发环境 |
|--------|----------|----------|
| OPcache | 启用 | 可选 |
| Redis 缓存 | 推荐 | 可选 |
| Gzip 压缩 | 启用 | 可选 |
| 慢查询日志 | 启用 | 启用 |
| Composer 优化 | `--no-dev --optimize` | 默认 |
| 静态资源缓存 | 30天 | 不缓存 |
- [5.17 链路追踪与指标](/zh/core/trace-metrics.html)
- [11.10 故障排查手册](/zh/deploy/troubleshooting.html)