169 lines
6.8 KiB
Markdown
169 lines
6.8 KiB
Markdown
# 11.7 性能调优
|
||
|
||
:::tip 概述
|
||
本节从 PHP、缓存、数据库、前端四个维度提供性能调优建议。
|
||
:::
|
||
|
||
## 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 ; 保留注释(反射文档注释、调试栈追踪依赖此配置)
|
||
```
|
||
|
||
:::warning OPcache 注意事项
|
||
`validate_timestamps = 0` 时,更新代码后必须重启 PHP-FPM 或手动清除 OPcache,否则不会生效。
|
||
:::
|
||
|
||
### PHP-FPM 进程池
|
||
|
||
```ini
|
||
; =============================================================================
|
||
; PHP-FPM 进程池配置
|
||
; 配置路径:/etc/php/8.3/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 → 排除开发依赖(phpunit/phpunit、laravel/pint 等)
|
||
# --optimize-autoloader → 优化自动加载器(生成 classmap,减少文件查找)
|
||
composer install --no-dev --optimize-autoloader
|
||
```
|
||
|
||
### Laravel 缓存命令
|
||
|
||
```bash
|
||
# 生产环境把配置、路由、视图编译进缓存,避免每次请求重新解析
|
||
php artisan config:cache
|
||
php artisan route:cache
|
||
php artisan view:cache
|
||
```
|
||
|
||
## 缓存层
|
||
|
||
### 使用 Redis
|
||
|
||
```ini
|
||
; .env — Redis 缓存配置(本项目默认即为 redis 驱动)
|
||
CACHE_STORE=redis ; 缓存驱动
|
||
SESSION_DRIVER=redis ; 会话驱动
|
||
QUEUE_CONNECTION=redis ; 队列驱动
|
||
REDIS_CLIENT=phpredis ; Redis PHP 扩展
|
||
REDIS_HOST=127.0.0.1 ; Redis 服务器地址
|
||
REDIS_PORT=6379 ; Redis 端口
|
||
REDIS_PASSWORD=your_redis_password ; Redis 密码
|
||
```
|
||
|
||
:::tip 缓存效果
|
||
- **DictCacheService(字典)**:两级缓存(请求级 + Laravel Cache),使用 Redis 后首次查库并写入 Redis,后续直接读缓存(TTL 3600 秒 / 1 小时),可减少 80%+ 的字典查询
|
||
- **ParamService(参数)**:仅请求级缓存(数据量小、变更即时生效,不落持久缓存)
|
||
:::
|
||
|
||
## 数据库层
|
||
|
||
### 索引优化
|
||
|
||
项目 SQL 脚本已内置大量索引(`uk_tenant_*` 唯一索引、`idx_*` 普通索引,覆盖租户隔离、用户名、手机号、状态、分类等高频查询)。**新增业务表或新增查询字段时**,再按需补充索引:
|
||
|
||
```sql
|
||
-- =============================================================================
|
||
-- 为常用查询字段添加索引(提升查询速度)
|
||
-- =============================================================================
|
||
-- 索引原理:类似书的目录,数据库通过索引快速定位数据行,避免全表扫描
|
||
-- 注意:索引会占用额外存储空间,且降低写入速度,只在高频查询字段上创建
|
||
-- =============================================================================
|
||
|
||
-- 新增业务表:租户隔离 + 状态筛选(本项目标准索引命名习惯)
|
||
ALTER TABLE laravel_example ADD INDEX idx_tenant_status (tenant_id, status);
|
||
|
||
-- 操作日志表:按时间范围查询(当前 SQL 脚本未建此索引,日志量大时建议补充)
|
||
ALTER TABLE laravel_operation_log ADD INDEX idx_create_time (create_time);
|
||
|
||
-- 用户表:平台侧按用户名直查(租户内查询已有 uk_tenant_username 覆盖)
|
||
ALTER TABLE laravel_user ADD INDEX idx_username (username);
|
||
```
|
||
|
||
### 慢查询日志
|
||
|
||
```ini
|
||
; MySQL my.cnf — 慢查询日志配置
|
||
; 配置路径:/etc/mysql/my.cnf 或 /etc/my.cnf
|
||
; 生效命令:sudo systemctl restart mysql
|
||
|
||
slow_query_log = 1 ; 启用慢查询日志
|
||
slow_query_log_file = /var/log/mysql/slow.log ; 日志文件路径
|
||
long_query_time = 2 ; 超过 2 秒的查询记录为慢查询
|
||
```
|
||
|
||
### 连接池
|
||
|
||
高并发场景建议配置持久连接:
|
||
|
||
```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,减轻服务器压力。CDN 场景下注意配置 `.env` 的 `TRUSTED_PROXIES` 以获取真实客户端 IP(见 [11.4 后端部署](/zh/deploy/backend.html))。
|
||
|
||
## 性能检查清单
|
||
|
||
| 检查项 | 生产环境 | 开发环境 |
|
||
|--------|----------|----------|
|
||
| OPcache | 启用 | 可选 |
|
||
| Redis 缓存 | 必需(缓存/会话/队列) | 必需 |
|
||
| Laravel 缓存(config/route/view) | 缓存(`php artisan *:cache`) | 清除状态(`*:clear`) |
|
||
| Gzip 压缩 | 启用 | 可选 |
|
||
| 慢查询日志 | 启用 | 启用 |
|
||
| Composer 优化 | `--no-dev --optimize-autoloader` | 默认 |
|
||
| 静态资源缓存 | 30天 | 不缓存 |
|