强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

11 - 性能优化

11 - 性能优化

掌握 Nextcloud 全栈性能优化:Redis 缓存、PHP OPcache、数据库调优、CDN 加速与 PHP-FPM 调优。


11.1 性能优化全景

┌─────────────────────────────────────────────────────────┐
│                   Nextcloud 性能优化层次                 │
│                                                         │
│  用户请求 → CDN → Nginx → PHP-FPM → Nextcloud          │
│                              │                          │
│                  ┌───────────┼───────────┐              │
│                  │           │           │              │
│             ┌────┴────┐ ┌────┴────┐ ┌────┴────┐        │
│             │ OPcache │ │  Redis  │ │ 数据库  │        │
│             │ 字节码  │ │  缓存   │ │  缓存   │        │
│             │  缓存   │ │ 会话锁  │ │ 查询缓存│        │
│             └─────────┘ └─────────┘ └─────────┘        │
│                                                         │
│  优化维度:                                               │
│  ├── PHP 层: OPcache + APCu + PHP-FPM 进程管理          │
│  ├── 缓存层: Redis (分布式缓存 + 文件锁 + 会话)          │
│  ├── 数据库: 索引 + 查询优化 + 连接池                    │
│  ├── Web 层: Nginx 缓存 + Gzip + HTTP/2                 │
│  ├── 传输层: CDN + 带宽优化                              │
│  └── 存储层: SSD + 预览预生成                            │
└─────────────────────────────────────────────────────────┘

性能瓶颈分析

瓶颈类型表现排查方法
CPU页面加载慢,PHP 进程 CPU 高top, htop
内存OOM Kill,swap 使用高free -h, vmstat
磁盘 I/O文件上传/下载慢iostat, iotop
网络同步慢,页面加载超时iftop, nload
数据库查询慢,连接数不足慢查询日志
PHP请求排队,502 错误PHP-FPM 状态

11.2 Redis 缓存配置

安装 Redis

# Ubuntu / Debian
sudo apt install -y redis-server

# 启动并设置开机自启
sudo systemctl enable --now redis-server

Redis 优化配置

编辑 /etc/redis/redis.conf

# ======== 内存管理 ========
maxmemory 512mb
maxmemory-policy allkeys-lru

# ======== 持久化(缓存场景可关闭以提升性能) ========
save ""                    # 关闭 RDB
appendonly no              # 关闭 AOF

# ======== 连接 ========
bind 127.0.0.1
port 6379
requirepass RedisPassword123!

# ======== 性能 ========
tcp-backlog 511
tcp-keepalive 300
timeout 0

# ======== 日志 ========
loglevel notice
logfile /var/log/redis/redis-server.log

Nextcloud Redis 配置

// config/config.php

// 分布式缓存
'memcache.distributed' => '\\OC\\Memcache\\Redis',

// 文件锁缓存
'memcache.locking' => '\\OC\\Memcache\\Redis',

// 本地缓存(单机用 APCu,集群用 Redis)
'memcache.local' => '\\OC\\Memcache\\APCu',

// Redis 连接参数
'redis' => array(
    'host' => 'localhost',          // 或 '/var/run/redis/redis.sock'
    'port' => 6379,
    'password' => 'RedisPassword123!',
    'dbindex' => 0,
    'timeout' => 1.5,
),

使用 Unix Socket(性能更好)

# /etc/redis/redis.conf
unixsocket /var/run/redis/redis.sock
unixsocketperm 770
// config/config.php
'redis' => array(
    'host' => '/var/run/redis/redis.sock',
    'port' => 0,                    // Socket 模式端口设为 0
    'password' => 'RedisPassword123!',
),
# 确保 www-data 可访问 socket
sudo usermod -aG redis www-data
sudo systemctl restart redis-server

Redis 连接测试

# 测试 Redis 连接
redis-cli -a RedisPassword123! ping
# 预期输出: PONG

# 查看 Redis 内存使用
redis-cli -a RedisPassword123! info memory

# 监控 Redis 命令
redis-cli -a RedisPassword123! monitor

11.3 PHP OPcache 配置

OPcache 原理

PHP 执行流程(无 OPcache):
  源码 → 词法分析 → 语法分析 → 字节码 → 执行

PHP 执行流程(有 OPcache):
  源码 → [缓存命中?] → 执行
              ↓ 未命中
          词法分析 → 语法分析 → 字节码 → 缓存 → 执行

推荐配置

; /etc/php/8.2/fpm/conf.d/10-opcache.ini

; 启用 OPcache
opcache.enable = 1
opcache.enable_cli = 1

; 内存大小(MB)
opcache.memory_consumption = 256

; 字符串interned buffer大小(MB)
opcache.interned_strings_buffer = 32

; 最大缓存文件数
opcache.max_accelerated_files = 20000

; 重新验证频率(秒)
; 0=每次请求都检查(开发环境)
; 60=每60秒检查一次(生产环境)
opcache.revalidate_freq = 60

; 保存注释(Nextcloud 需要)
opcache.save_comments = 1

; 快速关闭
opcache.fast_shutdown = 1

; JIT 编译(PHP 8.0+)
opcache.jit = 1255
opcache.jit_buffer_size = 128M

OPcache 状态监控

# 查看 OPcache 状态
php -r "var_dump(opcache_get_status());"

# 或创建监控脚本
cat << 'EOF' > /var/www/nextcloud/opcache-status.php
<?php
if (php_sapi_name() !== 'cli') {
    die('CLI only');
}
$status = opcache_get_status();
echo "=== OPcache Status ===\n";
echo "Enabled: " . ($status['opcache_enabled'] ? 'Yes' : 'No') . "\n";
echo "Used Memory: " . round($status['memory_usage']['used_memory'] / 1024 / 1024, 2) . " MB\n";
echo "Free Memory: " . round($status['memory_usage']['free_memory'] / 1024 / 1024, 2) . " MB\n";
echo "Cached Scripts: " . $status['opcache_statistics']['num_cached_scripts'] . "\n";
echo "Hit Rate: " . round($status['opcache_statistics']['opcache_hit_rate'], 2) . "%\n";
EOF

php /var/www/nextcloud/opcache-status.php

11.4 PHP-FPM 调优

进程管理策略

策略说明适用场景
static固定进程数负载稳定的生产环境
dynamic动态调整大多数场景
ondemand按需创建内存紧张的环境

动态进程配置

; /etc/php/8.2/fpm/pool.d/nextcloud.conf

[nextcloud]
user = www-data
group = www-data
listen = /run/php/nextcloud.sock
listen.owner = www-data
listen.group = www-data

; 动态进程管理
pm = dynamic
pm.max_children = 50                ; 最大进程数
pm.start_servers = 10               ; 启动进程数
pm.min_spare_servers = 5            ; 最小空闲进程
pm.max_spare_servers = 20           ; 最大空闲进程
pm.max_requests = 500               ; 单进程最大请求数(防内存泄漏)
pm.process_idle_timeout = 10s       ; 空闲进程超时

; 慢日志
slowlog = /var/log/php-fpm/nextcloud-slow.log
request_slowlog_timeout = 10s

; 请求超时
request_terminate_timeout = 300s

计算 max_children

内存计算公式:
  max_children = (总内存 - 系统保留内存 - 数据库内存 - Redis 内存) / 单个 PHP 进程内存

示例:
  总内存: 8GB
  系统保留: 1GB
  数据库: 2GB
  Redis: 512MB
  单个 PHP 进程: ~80MB

  max_children = (8192 - 1024 - 2048 - 512) / 80 ≈ 57

PHP-FPM 状态监控

; 添加状态页面
pm.status_path = /fpm-status
ping.path = /fpm-ping
# Nginx 配置
location ~ ^/(fpm-status|fpm-ping)$ {
    allow 127.0.0.1;
    deny all;
    fastcgi_pass unix:/run/php/nextcloud.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}
# 查看 FPM 状态
curl http://127.0.0.1/fpm-status

11.5 Nginx 优化

性能配置

# /etc/nginx/nginx.conf

# 工作进程数(等于 CPU 核心数)
worker_processes auto;

# 事件处理
events {
    worker_connections 2048;
    multi_accept on;
    use epoll;
}

http {
    # 启用 Gzip
    gzip on;
    gzip_vary on;
    gzip_comp_level 4;
    gzip_min_length 256;
    gzip_types
        application/javascript
        application/json
        application/xml
        text/css
        text/javascript
        text/plain
        text/xml
        image/svg+xml;

    # 启用 HTTP/2
    # listen 443 ssl http2;

    # 静态文件缓存
    location ~* \.(jpg|jpeg|png|gif|ico|svg|webp|css|js|woff2|woff|ttf)$ {
        expires 30d;
        add_header Cache-Control "public, no-transform";
        access_log off;
    }

    # PHP 文件缓存控制
    location ~ \.php$ {
        # 禁止缓存动态内容
        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }

    # 连接优化
    keepalive_timeout 65;
    keepalive_requests 100;

    # 缓冲区
    client_body_buffer_size 16k;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 16k;
    client_max_body_size 16G;

    # FastCGI 缓存(谨慎使用,可能影响动态内容)
    # fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=NC:100m inactive=10m max_size=1g;
}

11.6 数据库查询优化

MySQL 查询缓存优化

; /etc/mysql/mariadb.conf.d/90-nextcloud.cnf

[mysqld]
# InnoDB 缓冲池(最重要的参数)
innodb_buffer_pool_size = 2G              # 总内存的 50-70%
innodb_buffer_pool_instances = 2          # 多个实例提升并发

# 查询优化
query_cache_type = 0                      # MySQL 8.0 已移除,MariaDB 可设为 0
tmp_table_size = 64M
max_heap_table_size = 64M
sort_buffer_size = 4M
join_buffer_size = 4M
read_rnd_buffer_size = 4M

# 慢查询日志
slow_query_log = ON
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2

分析慢查询

-- MySQL: 查看慢查询统计
SELECT
    COUNT(*) as total_queries,
    ROUND(AVG(query_time), 3) as avg_time,
    MAX(query_time) as max_time
FROM mysql.slow_log
WHERE start_time > NOW() - INTERVAL 1 DAY;

-- 查看表状态
SHOW TABLE STATUS FROM nextcloud;

-- 分析特定查询
EXPLAIN SELECT * FROM oc_filecache WHERE path LIKE '%user/files/%';

定期维护

# 优化数据库表
sudo -u www-data php /var/www/nextcloud/occ db:add-missing-indices
sudo -u www-data php /var/www/nextcloud/occ db:add-missing-columns
sudo -u www-data php /var/www/nextcloud/occ db:add-missing-primary-keys

11.7 CDN 配置

适用场景

资源类型CDN 缓存说明
静态资源 (CSS/JS/图片)✅ 推荐大幅减少源站压力
应用资源✅ 推荐加速 Web 界面加载
用户文件❌ 不推荐安全性考虑,需认证
API 请求❌ 不推荐动态内容

Nginx CDN 配置

# 设置静态资源缓存头
location ~* \.(css|js|svg|gif|png|jpg|ico|woff2|woff|ttf|map)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
    add_header X-Content-Type-Options "nosniff";
    access_log off;
}

Cloudflare 配置建议

Cloudflare 设置:
├── SSL/TLS: Full (Strict)
├── 缓存级别: Standard
├── 浏览器缓存 TTL: 1 month (静态资源)
├── Always Online: ON
├── Brotli: ON
├── HTTP/2: ON
└── Page Rules:
    └── cloud.example.com/remote.php/* → Cache Level: Bypass

11.8 预览图优化

预生成预览图

# 安装预览生成应用
sudo -u www-data php /var/www/nextcloud/occ app:install preview_generator

# 配置预览尺寸
sudo -u www-data php /var/www/nextcloud/occ config:app:set \
  preview_generator previewSizes --value="32 64 128 256 512 1024"

# 预生成所有预览
sudo -u www-data php /var/www/nextcloud/occ preview:generate-all -vvv

# 设置 cron 定时生成
sudo crontab -u www-data -e
# 添加:
# 0 */4 * * * php -f /var/www/nextcloud/occ preview:generate-all

使用 Imagick 替代 GD

// config/config.php
'preview_lib' => 'Imagick',  // Imagick 比 GD 更快,质量更好
# 确保 Imagick 已安装
sudo apt install -y php8.2-imagick

11.9 性能监控

Prometheus + Grafana

# 安装 Nextcloud 导出器
sudo -u www-data php /var/www/nextcloud/occ app:install prometheus_nextcloud_exporter

核心监控指标:

指标说明阈值
active_users活跃用户数
php_fpm_active_processesPHP-FPM 活跃进程< max_children * 0.8
db_connection_count数据库连接数< max_connections * 0.8
cache_hit_rate缓存命中率> 95%
request_duration请求响应时间< 500ms
storage_usage存储使用率< 80%

简易性能测试

# 使用 ab 进行压力测试
ab -n 100 -c 10 -H "Authorization: Basic $(echo -n 'admin:password' | base64)" \
  https://cloud.example.com/ocs/v2.php/cloud/user

# 使用 wrk
wrk -t4 -c100 -d30s https://cloud.example.com/

11.10 性能优化检查清单

# 1. 检查 PHP OPcache
php -r "var_dump(opcache_get_status()['opcache_enabled']);"
# 应输出: bool(true)

# 2. 检查 Redis 连接
redis-cli -a RedisPassword123! ping
# 应输出: PONG

# 3. 检查缓存配置
sudo -u www-data php /var/www/nextcloud/occ config:system:get memcache.local
# 应输出: \OC\Memcache\APCu

# 4. 检查后台任务
sudo -u www-data php /var/www/nextcloud/occ background:cron
# 应输出: cron

# 5. 检查数据库索引
sudo -u www-data php /var/www/nextcloud/occ db:add-missing-indices

# 6. 检查 PHP 版本
php -v
# 推荐 PHP 8.2+

# 7. 检查 HTTP/2
curl -sI https://cloud.example.com | grep "HTTP/2"

11.11 注意事项

  1. Redis 持久化: 作为缓存使用时建议关闭持久化以提升性能
  2. OPcache 验证: 生产环境 revalidate_freq 设为 60,代码更新后需要清除缓存
  3. PHP-FPM 进程数: 不要设置过大,会导致内存耗尽
  4. CDN 缓存: 用户文件不要走 CDN,会导致认证问题
  5. JIT 编译: PHP 8.0+ 的 JIT 可提升约 10-20% 性能,但不是银弹
  6. 预览预生成: 首次访问大量文件时预览生成会消耗大量 CPU

11.12 扩展阅读


上一章: 10 - 安全加固 下一章: 12 - 备份恢复 — 自动备份、增量备份与灾难恢复。