TongWeb 应用日志落盘与 JVM 堆配置优化笔记
记录时间:2026-07-30
环境:K8s(dev 命名空间,信创 ARM64 集群)/ ArgoCD GitOps / gzeport-tongweb chart 1.0.10 / TongWeb 8.0.9.08 / JDK 11;共享存储jar-log-data-pvc(50Gi,RWO,storageClass=k8s-data)
一、背景与问题现象
TongWeb 类应用通过 gzeport-tongweb chart 部署,原来 values 里只把 /AppHome/logs、/AppLogs 挂到共享 PVC(jar-log-data-pvc)。Pod 一旦重建,下面这些排障产物全部丢失:
- TongWeb 自身日志:
logs/server/server.log、logs/audit/* - JVM 排障产物:
logs/jvm/jvm.log、GC 日志、hs_err_pid*.log(崩溃日志)、heap_*.hprof(堆 dump)
目标:让这些产物落盘到 PVC,Pod 重建后仍可追溯。
涉及范围:dev 命名空间共 19 个 tongweb 应用(dyck 12、szzx 5、hkwl 2)。改动分两层:共享的 configmap-tongweb.yaml(tongweb.xml)和各应用 values 的挂载。
二、关键机制梳理(动手前先理清)
2.1 TongWeb 日志分流:哪些进文件、哪些只在 console
tongweb.xml 的 <loggers><server> 节点三个参数决定日志走向(对应 TongWeb 官方文档「系统日志与应用日志分离」):
| 参数 | 取值 | 作用 |
|---|---|---|
takeoverSystemPrint |
true |
接管应用 System.out / System.err |
printToConsoleOnly |
true |
被接管的系统打印仅控制台,不写文件 |
takeoverJUL |
true |
接管 java.util.logging,写入 server.log |
不同来源日志的落盘情况:
| console 里的内容 | 是否落盘(写 PVC) |
|---|---|
[INFO] - Server Info / Deploying app / Server startup 等 TongWeb 自身日志 |
✅ 写 logs/server/server.log(logToFile=true) |
| 框架/业务日志(c3p0、Spring,经 logback stdout appender) | ❌ 仅 console(被 takeoverSystemPrint 接管,printToConsoleOnly=true) |
应用代码里的 System.out.println |
❌ 仅 console |
应用 java.util.logging 日志 |
✅ 写 server.log |
Cannot open logs/jvm/jvm.log 这类 |
❌ 仅 console(JVM 直出 stderr) |
要点:挂 PVC 只接得住
server.log(含 JUL)和audit,接不住System.out。后者要集中留存只能靠集群级 Filebeat / Fluentd 采集节点/var/log/containers/*.log,不该在应用 values 里加 sidecar。
2.2 TongWeb 的 JVM 参数从哪来
TongWeb 启动方式是 TongWebMain start,JVM 参数有两个来源,都会进进程命令行:
<start-args>(tongweb.xml):TongWeb 启动脚本解析,拼到 java 命令行;JAVA_OPTS环境变量:chart 把 values 的jvm.opts注入到这里,启动脚本也会采用(TongWeb 8.x 的 startserver / startd 支持,见 release-notes)。
用 cat /proc/<pid>/cmdline | tr '\0' '\n' 可以看到两者都在进程里。
三、操作过程
3.1 试点 airedo:只挂 logs/server 子目录
在 values 的 mount.volumeMounts 增加一条,复用已有 log-data volume,volumes 段不动:
# 仅挂载 TongWeb server 日志子目录(logs/server/server.log)落盘到共享 PVC,Pod 重建后保留
- mountPath: /AppHome/TongWeb8/domains/domain1/logs/server
subPath: '{{ .Release.Name }}/tongweb'
name: log-data
为什么只挂
logs/server而不是整个logs/:挂整个logs/会用空 PVC 子目录遮盖镜像里预置的logs/jvm、logs/gc子目录,JVM 启动时-XX:LogFile=logs/jvm/jvm.log因父目录不存在而写失败,回退/tmp。只挂server子目录就不遮盖 jvm/gc/audit,副作用消失,也不需要 initContainer 预建目录。试错:第一版确实挂了整个
logs/,启动日志第一行就报Cannot open file logs/jvm/jvm.log ... Forcing -XX:LogFile=/tmp/jvm.log,改成只挂logs/server后消失。
3.2 调整共享 configmap:堆交给 MaxRAMPercentage + JVM 产物路径挪进挂载点
application/init/configmap-tongweb.yaml 的 <start-args> 改动:
| 项 | 改动前 | 改动后 | 原因 |
|---|---|---|---|
-Xms2048m / -Xmx2048m |
写死堆 2G | 删除(注释保留) | 让 values 的 MaxRAMPercentage 接管 |
-XX:LogFile |
logs/jvm/jvm.log |
logs/server/jvm.log |
落进挂载点,避免子目录不存在 |
-XX:ErrorFile |
logs/hs_err_pid%p.log |
logs/server/hs_err_pid%p.log |
同上,落盘 |
-XX:HeapDumpPath |
logs/heap_*.hprof |
logs/server/heap_*.hprof |
同上,落盘 |
改完用 kubectl apply --dry-run=client -f application/init/configmap-tongweb.yaml 验证 YAML 合法。
为什么
jvm.log路径不能带中间目录(如logs/server/jvm/jvm.log):JVM 不自动建多级目录,挂载点logs/server首次是空 PVC,其下jvm子目录不存在,会再次Cannot open回退/tmp。直接落挂载点根logs/server/jvm.log才稳。显式
-Xms/-Xmx会架空MaxRAMPercentage:MaxRAMPercentage只在未指定-Xms/-Xmx时才参与计算;显式-Xms/-Xmx优先级更高,与参数先后顺序无关。原 configmap 写死-Xms2048m -Xmx2048m,导致 values 配的MaxRAMPercentage=75不生效、堆恒为 2G。删掉-Xms/-Xmx后才按容器 limit 百分比算。
3.3 推广到其余 18 个 tongweb 应用
按 airedo 模式,给每个 values 的 mount.volumeMounts 加 logs/server 挂载。锚点是 /AppLogs 块到 volumes: 之间,按有无空行分两类精确编辑:
- A 型(
/AppLogs块紧接volumes:,无空行):14 个 - B 型(中间有空行):4 个(airmanifest、roadmft-web、wmyc、datashow)
要点:批量改 values 前必须逐个读原文确认精确锚点。infostat、qjksh 一开始被脚本输出误判为 B 型,读全文才发现是 A 型。
四、验证(airedo 重启后)
# 1. 堆是否按百分比算(最权威,jcmd)
pid=$(pgrep -f TongWebMain | head -1)
jcmd $pid VM.flags | tr ' ' '\n' | grep -iE 'MaxHeapSize|InitialHeapSize|MaxRAMPercentage'
# 预期:MaxHeapSize=3221225472(3Gi,4Gi×75%)、InitialHeapSize=2583691264(2.4Gi,4Gi×60%)、MaxRAMPercentage=75
# 2. jvm.log 是否落盘(不再回退 /tmp)
ls -l ~/TongWeb8/domains/domain1/logs/server/
# 预期:server.log、jvm.log 都在,owner gzapps,jvm.log 有内容
airedo 实测:MaxHeapSize=3221225472(3Gi),logs/server/ 下 jvm.log(73KB)+ server.log 齐全。
别用
jps -lvm判断堆参数:排查时一度用jps -lvm | grep Xmx只看到-Xms8m,误以为堆配置全丢——那是 jps 工具自己的默认堆,且 jps 输出可能截断。判断 JVM 实际参数用/proc/<pid>/cmdline或jcmd <pid> VM.flags。
五、注意事项
- 改 configmap 是 dev 共享:19 个应用都受影响,ArgoCD 同步 + 滚动重建后才生效;Pod 用的是它启动那一刻的 configmap 快照,后续改动要等下次重建。
- 堆会上调:删
-Xms/-Xmx后堆从固定 2G 变成按 limit 百分比(多数 3G,gzeport-sso-web8Gi×75%=6G),重建后盯一下 GC 和容器内存。 requests.memory(2Gi) < 实际堆(~2.4-3G):overcommit 现状就有、略加重,非质变;要彻底消除可把 requests 也调到 3Gi。- 没配
MaxRAMPercentage的应用不能直接删-Xms/-Xmx:否则堆掉到 JDK11 默认 25%。本次 19 个应用盘点确认都配了,才安全。