——PVE + Docker + Web 应用场景下的真实优化案例

一、问题背景

在一台运行于 Proxmox VE(PVE)上的 Linux 虚拟机中,同时部署了多种服务,包括:

  • 多个基于 PHP 的内容与文件管理系统
  • 一套基于 WebSocket 的实时通信服务(Docker 容器)
  • 一套 Java 虚拟机驱动的服务
  • 一个关系型数据库服务(为前述 PHP 应用提供数据支持)

该虚拟机分配了约 23GB 内存,长期观察到:

  • 数据库进程占用内存超过 1GB
  • 系统整体内存使用率偏高
  • 在 PVE 执行在线快照备份时,依赖数据库的 Web 应用会短暂不可用

初步怀疑数据库内存配置不合理。


二、关键发现:InnoDB Buffer Pool 被设置为 10GB

通过查询数据库内部参数发现:

SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW VARIABLES LIKE 'innodb_buffer_pool_instances';

结果显示:

  • innodb_buffer_pool_size = 10737418240(10GB)
  • innodb_buffer_pool_instances = 4

这是一套典型的数据库专用服务器配置,而当前系统实际上是一个多服务混合运行的 Web 主机

在这种环境下:

  • PHP Web 应用的数据规模通常较小
  • 访问高度集中在少量热点表
  • 给数据库分配 10GB 缓存只会抢占系统资源

其直接后果是:

  • Linux 页缓存被挤压
  • Docker、JVM、Web 服务可用内存下降
  • PVE 快照 freeze 时间被放大

三、目标:尽可能小,但不影响实际性能

该系统的目标是:

在不影响 Web 应用体验的前提下,将数据库内存压缩到合理的下限。

最终采用如下配置:

[mysqld]
innodb_buffer_pool_size = 512M
innodb_buffer_pool_instances = 1
max_connections = 30

设计原则:

  • 512MB 足以容纳所有热点数据
  • 单实例 buffer pool 避免碎片化
  • 限制连接数,防止 PHP 异常时拖垮数据库

四、效果:数据库从“内存黑洞”变为“可控组件”

重启后验证:

SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW VARIABLES LIKE 'innodb_buffer_pool_instances';
SHOW VARIABLES LIKE 'max_connections';

数据库进程内存占用:

≈ 530 MB

与 512MB 的 buffer pool 高度一致,说明配置准确生效。


五、整机内存结构发生根本变化

优化后系统状态:

Mem total: 23Gi
Used (进程):   ~6–7Gi
buff/cache:    ~6–7Gi
Available:     ~16Gi
Swap:          0

含义:

  • 数据库不再私有占用 10GB
  • 释放出的内存由 Linux 统一管理为 page cache
  • Web 文件、数据库页、日志等进入高效缓存层
  • 整机可用内存显著增加

本质变化是:

从“数据库私有缓存主导”
→ “操作系统统一缓存主导”

这对多服务 Web 主机是最优模型。


六、关于 Node.js 进程的澄清

在进程列表中发现多个 node main.js 占用数百 MB 内存。

进一步追踪表明:

  • 这些进程位于 Docker 容器 cgroup
  • 工作目录为 /app/bundle/programs/server
  • 同容器内还有运行时沙箱进程

这确认其来源是实时通信服务容器的后端框架,而非异常进程或入侵。


七、为何 PVE 备份期间只有 Web 应用掉线

现象:

  • 在 PVE snapshot 期间
  • 只有依赖数据库的 PHP Web 应用会短暂不可访问
  • 其他 Docker 服务和内存型服务保持正常

原因是:

  • PVE snapshot 会执行文件系统 freeze
  • InnoDB 需要同步写入 redo log / 数据页
  • 消费级 NVMe 无写缓存,fsync 会被真实阻塞
  • PHP 请求等待数据库 → Web 超时 → 看起来“站点挂了”

而实时通信服务和 JVM 服务主要依赖内存与异步 I/O,不会被 freeze 直接影响。


八、关于是否缩小虚拟机内存

在数据库内存回收后,虚拟机真实进程仅使用约 6–7GB,其余为 Linux cache。

虽然可以将 VM 内存从 23GB 压缩到更小,但考虑到:

  • PVE snapshot 依赖 page cache
  • cache 越大,freeze 越短
  • 增量备份越快

最终选择保持当前内存分配,以换取:

更短冻结时间
更快增量备份
更少服务抖动


九、结论

这次优化的核心并非“让数据库更小”,而是:

把系统从“数据库专用机思路”拉回“多服务主机的工程平衡状态”。

通过将 InnoDB buffer pool 从 10GB 调整为 512MB:

  • 数据库从内存黑洞变为受控组件
  • 操作系统重新掌控缓存
  • Docker、Web、JVM 获得更充足资源
  • 快照冻结时间缩短
  • 整机稳定性与响应性显著提升

这是一个典型的自托管环境中“过度调优回退”的成功案例

Leave a Reply

Your email address will not be published. Required fields are marked *