相同Tomcat镜像在两台Debian服务器运行出现行为差异咨询
差异原因说明
带PS前缀的内存池名称是JVM使用Parallel Scavenge系列垃圾收集器的典型标识,无该前缀则代表使用了Serial系列单线程垃圾收集器。
OpenJDK 8的默认垃圾收集器会根据当前运行环境的硬件资源动态选择:
- 当运行环境CPU核心数≥2且可用内存≥2GB时,JVM默认启用
Parallel Scavenge(新生代) + Parallel Old(老年代)的组合,内存池名称会带PS前缀 - 不满足上述硬件条件时,JVM默认启用
Serial(新生代) + Serial Old(老年代)的单线程收集器组合,内存池名称无PS前缀
你使用的tomcat:8.5-jdk8-openjdk镜像没有硬编码指定JVM垃圾收集器参数,因此容器启动时JVM会直接探测可用硬件资源,出现差异的核心原因有两种:
- 两台Debian服务器本身的CPU核心数、总内存硬件配置不一致
- 两台服务器上Docker的默认容器资源配额配置不同,比如某一台默认限制容器只能使用1核CPU/更小内存上限,导致JVM探测到的硬件资源不满足Parallel收集器的启用条件
其他潜在差异说明
因为JVM的默认参数是根据可用硬件动态生成的,除了垃圾收集器和内存池命名差异外,大概率还存在以下未发现的差异:
- 堆内存默认配置不同:OpenJDK 8默认最大堆内存为可用内存的1/4,若两台容器的可用内存不同,Tomcat可使用的最大堆内存也不一样
- GC性能表现不同:Parallel收集器的吞吐量更高,适合多核大内存场景;Serial收集器的停顿时间更可控,适合低配置小内存场景,两者的GC频率、停顿时长都会有差异
- 内存分代比例不同:不同垃圾收集器的默认新生代、老年代内存比例存在差异,会影响对象分配和GC的触发时机
验证与统一配置方法
你可以分别进入两个运行中的Tomcat容器,执行以下命令验证垃圾收集器的差异:
java -XX:+PrintFlagsFinal -version | grep -E "UseParallelGC|UseSerialGC"
如果需要让两台服务器的容器行为完全一致,可以在启动命令中添加固定的JVM参数,硬编码指定垃圾收集器和内存配置,修改后的启动命令示例如下:
docker run --name tomcat-test -it -p 8083:8080 \ -v /tmp/tomcat-users.xml:/usr/local/tomcat/conf/tomcat-users.xml \ -v /tmp/context.xml:/tmp/context.xml \ -e JAVA_OPTS="-XX:+UseParallelGC -Xms1g -Xmx1g" \ tomcat:8.5-jdk8-openjdk /bin/bash -c "mv /usr/local/tomcat/webapps /usr/local/tomcat/webapps2; mv /usr/local/tomcat/webapps.dist /usr/local/tomcat/webapps; cp /tmp/context.xml /usr/local/tomcat/webapps/manager/META-INF/context.xml; catalina.sh run"
内容的提问来源于stack exchange,提问作者Meta
相关产品推荐
相关产品推荐

