Linux 与系统

小内存服务器运行 Halo:OOM 排查、JVM 预算与 Swap 边界

小内存服务器同时运行 Halo、数据库、反向代理和面板时,某个进程的占用上升就可能挤压其他服务。应先定位退出原因,再为各进程分配预算,最后用请求延迟和内存压力验证调整效果。本文将原有几篇零散笔记合并为排查方法;现有材料缺少原始事故日志,文中参数和现象均不作为实测结果。

小内存服务器同时运行 Halo、数据库、反向代理和面板时,某个进程的占用上升就可能挤压其他服务。应先定位退出原因,再为各进程分配预算,最后用请求延迟和内存压力验证调整效果。本文将原有几篇零散笔记合并为排查方法;现有材料缺少原始事故日志,文中参数和现象均不作为实测结果。

先确定是否发生 OOM

bash6 行
free -h
vmstat 1 10
journalctl -k -b --no-pager | rg -i 'out of memory|oom|killed process'
docker stats --no-stream
# 使用现场容器名;退出码只提供线索
docker inspect halo --format '{{.State.OOMKilled}} {{.State.ExitCode}} {{.RestartCount}}'

退出码 137 表示进程收到 SIGKILL,也可能来自人工停止或超时后的强制结束。需要结合 OOMKilled、内核日志和 cgroup 事件确认原因。主机还有可用内存时,容器仍可能触及自身限制;反过来,容器未设置限制也可能消耗主机余量。

在 cgroup v2 系统中,先从进程的 /proc/<pid>/cgroup 确定所属路径,再读对应的 memory.current、memory.max、memory.events 和 memory.swap.max。memory.events 的计数需要比较观察窗口前后的增量。内核文档说明了限制和事件的含义。

JVM 堆只是进程预算的一部分

可用预算可以写成:

text2 行
主机内存预算 = 操作系统与页缓存余量 + 各服务预算 + 突发余量
Java 进程预算 = 堆 + 元空间 + 线程栈 + 直接内存 + JIT/原生库等开销

-Xmx 只限制堆上限,不能限制整个 Java 进程。插件、连接池和线程数量都会影响堆外占用。设置容器内存上限时,应给堆外部分留出余量;数据库缓存也要单独计入主机预算。

先查看实际生效的 JVM 参数和启动日志,确认容器环境变量确实传递给 Java。Halo 镜像、JDK 和插件版本应作为同一组配置记录。不同版本的部署要求以官方 Docker Compose 文档为准,不能把一个固定堆值推广到所有安装。

Swap 如何缓解压力

Swap 把部分匿名页换出到存储,能为瞬时内存压力提供缓冲;持续换入换出会增加 I/O 等待和请求延迟。已有 Swap 占用且 si/so 长期接近零,与不断换页的状态需要分别判断。

创建 Swap 前检查文件系统支持、磁盘空间和现有配置。下面仅演示在支持普通 swapfile 的文件系统上创建新文件;Btrfs、稀疏文件和快照环境需采用对应文件系统的方法。

bash15 行
swapon --show
# 确认 /swapfile 尚不存在;1 GiB 仅用于说明流程
sudo bash <<'SH'
set -euo pipefail
if [ -e /swapfile ] || [ -L /swapfile ]; then
    echo '/swapfile 已存在,停止操作' >&2
    exit 1
fi
(umask 077; set -o noclobber; : > /swapfile)
dd if=/dev/zero of=/swapfile bs=1M count=1024 status=progress
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
SH
swapon --show

上面各步必须逐项确认成功,发现已有 /swapfile 时停止,不能继续格式化。确认换页工作正常后,再按本机运维流程持久化到 /etc/fstab,避免重复条目。容器能否使用 Swap 还取决于容器限制与主机策略。

调整时一次只改变一个变量

先限制异常并发、停用确认无用的插件或调整单个连接池,再观察同一流量窗口。记录堆占用、进程 RSS、可用内存、Swap 换页速率、错误率以及请求延迟分位数。重启后短时间变快只能说明状态被清空,还需要覆盖流量高峰和定时任务。

如果数据库、Halo 与面板的合理预算总和已经超过机器容量,需要减少常驻组件、拆分服务或增加容量。继续压缩堆可能把 OOM 转成频繁 GC,延长超时则可能让排队占用更多内存。

如何判断恢复

恢复检查应同时包含:内存相关事件没有持续增加、请求能完成、延迟符合目标、后台任务成功,以及备份可以恢复。观察持续时间由业务高峰和任务周期决定。没有这些记录时,只能描述配置调整,不能声称系统已稳定运行。

← 返回文章