这是典型的「资源限制未对齐」问题:Docker CPU 限制与 Yii2 缓存、PHP-FPM 配置不匹配,导致频繁失效、调度争抢;MySQL 持久连接堆积、AssetManager 路径错位、Redis 时间不同步等共同引发性能下降。

容器里 Yii2 应用响应变慢,docker stats 显示 CPU 飙高但 PHP 进程没满载
这是典型的「资源限制未对齐」问题:Docker 的 --cpus 或 cgroups 限制了 CPU 时间片,但 Yii2 的 opcache 和 APCu 缓存策略仍按物理机逻辑配置,导致频繁缓存失效、重复编译。PHP-FPM 子进程数若还沿用 pm.max_children = 50 这类旧值,反而会加剧调度争抢。
实操建议:
- 在
php-fpm.conf中把pm.max_children改为容器内存的 1/40(单位 MB),比如 512MB 容器 → 设为12;同时启用pm = ondemand - 强制关闭
opcache.validate_timestamps(设为0),容器镜像构建阶段就预热 opcache,运行时不再检查文件修改时间 - 确认宿主机内核开启
CONFIG_MEMCG_SWAP_ENABLED,否则 Docker 的--memory限制在 swap 溢出时会静默失效,Yii2 大数组序列化可能直接 OOM 而不报错
MySQL 连接池耗尽,yii\db\Exception 报 “Too many connections” 却查不到活跃连接
容器网络下,Yii2 默认的 PDO::ATTR_PERSISTENT => true 会与 Docker 的 DNS 缓存、连接复用机制冲突——每个 PHP-FPM worker 持有独立持久连接,而容器重启后旧连接未被 MySQL 主动回收,wait_timeout 又设得过大(默认 28800 秒),连接堆积在服务端却显示为 Sleep 状态。
实操建议:
- 在
common/config/main-local.php的数据库组件中显式关闭持久连接:'attributes' => [PDO::ATTR_PERSISTENT => false] - 把 MySQL 容器的
wait_timeout降到300(5 分钟),配合 Yii2 的Connection::setActive(false)手动释放,避免长 Sleep 占位 - 用
docker exec -it mysql mysql -e "show processlist;" | grep Sleep | wc -l实时盯住 Sleep 连接数,超过 20 就要查 Yii2 的事务是否未正确 commit/rollback
AssetManager 生成的 JS/CSS 文件 404,本地开发正常但容器里报错
根本原因是 AssetManager::basePath 默认指向 @webroot/assets,而容器中 Nginx 的 root 配置若写成 /app/web,但实际代码挂载路径是 /var/www/html,导致生成的 asset 路径和 Nginx 可访问路径错位。更隐蔽的是,chmod 权限在 Docker build 阶段被覆盖,assets/ 目录不可写,Yii2 静默失败却不报错。
实操建议:
- 在
web.php中硬编码 asset 路径:'assetManager' => ['basePath' => '/var/www/html/assets', 'baseUrl' => '@web/assets'] - Dockerfile 构建最后加一句:
RUN mkdir -p /var/www/html/assets && chown -R www-data:www-data /var/www/html/assets - 删掉
assets/目录后,用./yii asset/compress预生成静态资源包,避免运行时动态生成——这对 CI/CD 流水线尤其关键
Redis 缓存命中率骤降,redis-cli info keyspace 显示 db0 key 数暴涨但业务量没变
Yii2 的 CacheDependency 在容器时间不同步时会出问题:宿主机时间快于容器,导致依赖时间戳早于当前时间,缓存永远不更新;反过来,容器时间慢,则所有依赖过期判断失效,缓存被大量误判为“已过期”,反复重建。另外,yii\caching\RedisCache 默认 keyPrefix 是空字符串,多实例共用一个 Redis 时 key 冲突,互相覆盖。
实操建议:
- 启动容器时必须加
--volume /etc/localtime:/etc/localtime:ro,禁止容器使用 UTC 时间 - 在 Redis 缓存组件配置中强制指定
'keyPrefix' => 'yii2-prod-',前缀带环境标识 - 把
CacheDependency::ensureCheck改为false,改用TagDependency+ 主动标记失效,规避时间判断逻辑
调优不是堆参数,而是让 Yii2 的缓存、连接、资产三套机制真正理解自己跑在受限的、隔离的、时间可能漂移的容器里——漏掉任意一环,性能瓶颈就会以最意想不到的方式冒出来。



















