Files
lionwebsite-backend/docs/MEMORY_TUNING_2026-09-21.md
root e03a2e007b netty 按需声明,并记录 jar 运行期的低内存调优
netty-all 是聚合 pom,会拖进 5 个平台的 native-quic、各架构的 epoll/kqueue/
io_uring 传输以及 htt3/mqtt/redis 等一堆用不到的 codec。主站实际只用
Bootstrap/NioEventLoopGroup/NioSocketChannel/ByteBuf/ByteToMessageCodec/
LengthFieldBasedFrameDecoder/LoggingHandler/Promise,因此收敛为
transport + codec-base + handler(含 buffer/common/resolver 传递依赖)。

效果:jar 68.1MB -> 52.2MB,netty 模块 50 -> 7,进程 RSS 291MB -> 约 227MB。
433 个测试全绿。hutool 未动。

同时把 jar 运行期的 systemd JVM 参数与前后实测数据记入
docs/MEMORY_TUNING_2026-09-21.md,避免这些只存在于服务器 drop-in 的参数
在下次重新部署时丢失。
2026-09-21 17:27:17 +08:00

3.9 KiB
Raw Permalink Blame History

2026-09-21 低内存调优记录(jar 运行期)

编译机未上线期间,两个后端都以 jar 方式运行。本机为 2 核 / 2.9G,活跃堆很小但 RSS 偏高, 做了一轮只改 JVM 参数与依赖声明的低内存调优。全程未改业务代码。

实测前后对照

服务 项目 调优前 调优后
主站 lionwebsite RSS 291 MB 约 227 MB
主站 lionwebsite jar 体积 68.1 MB 52.2 MB
主站 lionwebsite netty 模块 50 个 7 个
主站 lionwebsite 线程数 40 37
存储节点 storageNode RSS 171 MB 约 155-162 MB
存储节点 storageNode netty 模块 35 个 5 个
存储节点 storageNode 线程数 24 20-22

调优前后堆使用都在 40-52 MB 量级,RSS 的主要成分是元空间、代码缓存与各类映射, 因此收益主要来自收敛预留和减少类加载面,而不是堆。

一、JVM 参数(systemd drop-in,不在版本控制内)

主站 /etc/systemd/system/lionwebsite.service.d/jar-run.conf:

/usr/local/jdk-25/bin/java -Xmx256m -Xss512k -XX:MaxMetaspaceSize=160m \
  -XX:+UseSerialGC -XX:+UseCompactObjectHeaders \
  -XX:ReservedCodeCacheSize=96m -XX:+ExitOnOutOfMemoryError \
  -jar /home/lionwebsite/lionwebsite.jar

存储节点 /etc/systemd/system/storageNode.service.d/jar-run.conf:

/usr/local/jdk-25/bin/java -Xmx192m -Xss512k -XX:MaxMetaspaceSize=96m \
  -XX:+UseSerialGC -XX:+UseCompactObjectHeaders \
  -XX:ReservedCodeCacheSize=96m -XX:+ExitOnOutOfMemoryError \
  -cp /root/gallery/storageNode/storageNode-jar.jar:/root/gallery/storageNode/lib/* lion.Main

取值依据:

  • UseSerialGC:小堆、低吞吐场景,省掉 G1 的分区元数据与并发标记线程。存储节点原本就是默认 SerialGC,主站原本是默认 G1,本次对齐。
  • UseCompactObjectHeaders:对象头 12 到 8 字节,堆内以 String 与 map 节点为主时收益直接。
  • ReservedCodeCacheSize=96m:原先 240m 预留,实测主站只用约 14 MB、节点约 6 MB。
  • -Xmx 收敛:主站由 384m 到 256m,节点由 256m 到 192m,相对活跃堆仍留 4-6 倍余量。

回滚:恢复同目录 jar-run.conf.bak.20260921T090605Z(主站)或 jar-run.conf.bak.20260921T090746Z(节点)后 daemon-reload 加 restart。

二、依赖精简(已入库)

netty-all 是聚合 pom,会拖进全部模块。两个后端只用到 NIO 传输与基础编解码, 因此改为按需声明:

  • 主站(netty 4.2.17):netty-transport 加 netty-codec-base 加 netty-handler。 handler 用于 RemoteService 的 LoggingHandler 协议调试日志。
  • 存储节点(netty 4.1.138):netty-transport 加 netty-codec。 节点侧未使用 handler 模块的类,故不声明。4.1 无独立 codec-base,编解码基类在 netty-codec。

剔除的内容包括 5 个平台的 native-quic、aarch64 与 riscv64 与 osx 的 epoll 与 kqueue 与 io_uring 传输、 以及 codec-http3 与 mqtt 与 redis 与 smtp 与 stomp 与 xml 与 protobuf 等。

hutool-all 未调整。

三、已评估但未采用:AOT 缓存

JDK 25 的 -XX:AOTCache 可免原生编译生成类缓存。实测交替 A/B 各两轮:

启动耗时 RSS
无 AOT 6.37s / 6.74s 220.9 MB / 223.1 MB
带 AOT 6.27s / 6.36s 221.4 MB / 222.7 MB

启动约快 0.2s(噪声量级),RSS 与元空间均无改善,代价是 80 MB 缓存文件且每次发版需重训。 按降低内存的目标不值得,故未在生产启用。

四、遗留与后续

  • 原生编译机恢复后应重新评估原生镜像:内存会显著低于 jar,届时上述 JVM 参数失去意义。
  • 存储节点目录内仍保留 lib.bak.20260921T091617Z(47 jar)与 storageNode.jar.bak.*,为本次回滚路径。
  • 两个 jar-run.conf 的 JVM 参数只存在于服务器 drop-in,未纳入版本控制;重新部署时需按本文恢复。