通过配置通用Java Virtual Machine(JVM)的垃圾回收机制(Garbage Collection Mechanism)和Just-In-Time(JIT)参数,能够更好地在Java应用启动过程中使用ACS的柔性变配能力。本文介绍和Java应用启动加速相关的ParallelGCThreads
、ConcGCThreads
和CICompilerCount
三个JVM参数的推荐配置方法。
背景介绍
Java应用在启动阶段需要经历类加载、字节码编译和优化的阶段,这个阶段对于一些复杂的应用而言,可能要持续几分钟甚至十几分钟的时间。通常在这个阶段Java应用占用了超过一半的资源执行非应用代码的加载、编译的逻辑。而在应用预热完成进入稳定运行态后,这些资源会处于空闲状态。因此您可以通过ACS的柔性算力变配能力,在Java应用启动时提供更多的算力来加速应用启动。
在JVM虚拟机中普遍存在编译线程、用户进程和垃圾回收线程,这些线程会在Java应用启动以及稳定运行的不同阶段,以不同的比例共同占据整个Java应用的资源。 为了使Java应用能更好地发挥应用启动加速的效益,同时保证Java稳态运行时的性能,需要根据业务自身的特征,调整JVM参数配置从而合理地分配线程资源。
变配相关JVM参数推荐配置
下面将重点介绍和应用启动加速相关的3个重要JVM参数:ParallelGCThreads
、ConcGCThreads
和CICompilerCount
,以及它们的推荐配置参数。
假设用户程序设置的实际CPU核数是
JVM参数 | 参数说明 | 推荐配置参数 | |
| 并行GC的线程数。表示并行垃圾回收器使用的线程数量。 | 若 若 | |
| 并发GC的线程数。这些线程与应用程序线程并发运行,以减少停顿时间,所以需要给业务线程保留足够的线程数资源。 | 配置值计算方法 | |
| JIT编译线程数。此数值与程序的执行效率相关。频繁的JIT编译可能会导致性能瓶颈,因此不合理的JIT编译线程数会影响程序的执行效率。若配置过少的JIT线程数,因为解释执行效率较低的原因,可能会导致方法执行慢并且占用过高的CPU资源。 | 变配后CPU核数( |
|
1 | 2 | ||
2 | 2 | ||
4 | 3 | ||
8 | 3 | ||
16 | 8 | ||
32 | 10 | ||
64 | 12 |
典型场景配置参考
编排配置
在一个典型Java应用创建实例时,通过柔性变配多分配1倍的CPU资源, 同时变配维持到应用Ready后足够长时间(保证应用充分预热),一般可以观察到比较显著的加速效果。 如果Java应用要加载的库比较多,或者除了JVM自身编译以及预热外,应用有额外的耗时的初始化动作,变配的持续时间相对需要更长。
由于根据变配后的核数配置的GC和JIT的线程数,在降配后会超出实际分配的CPU数,如果应用在启动阶段没有完全预热,而是在降配后预热,在高负载的情况,可能会导致GC和JIT线程与应用争抢CPU资源。针对此情况,应该让应用在启动阶段升配的情况尽可能的完成应用的预热。
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: spring-with-burst
name: spring-with-burst
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: spring-with-burst
minReadySeconds: 400 # 推荐配置略大于变配持续时间的值, 从而保证在变配结束后,能够检验实例的状态
template:
metadata:
annotations:
alibabacloud.com/startup-cpu-burst-factor: '2' #设置启动扩容倍数为2, 即初始1C会以2C启动
alibabacloud.com/startup-cpu-burst-duration-seconds: "300" #默认的30s变配持续时间较短,大部分Java应用能在10分钟内启动完成,再加上5分钟足够完成预热阶段。建议根据应用的实际情况, 设置大于默认值的变配持续时间。
scaling.alibabacloud.com/enable-inplace-resource-resize: 'true' # 声明开启热变配
labels:
alibabacloud.com/compute-class: general-purpose
alibabacloud.com/compute-qos: default
app: spring-with-burst
spec:
containers:
- image: 'registry.cn-hangzhou.aliyuncs.com/acs-demo-ns/demo-java:java-with-metrics-v1'
imagePullPolicy: IfNotPresent
name: spring
ports:
- containerPort: 8080
protocol: TCP
resources:
limits:
cpu: 1
memory: 4Gi
requests:
cpu: 1
memory: 4Gi
JVM配置
按1倍升配的CPU配置, 可以参照如下的JVM参数配置:
原CPU核数 | 变配后CPU核数 | ParallelGCThreads | ConcGCThreads | CICompilerCount |
0.5 | 1 | 1 | 1 | 2 |
1 | 2 | 2 | 1 | 2 |
2 | 4 | 4 | 1 | 3 |
4 | 8 | 8 | 2 | 3 |
8 | 16 | 13 | 3 | 8 |
您可以在对应容器内通过以下Java命令检查Java版本的默认线程配置(例如ParallelGCThreads):
java -XX:+PrintFlagsFinal -version | grep ParallelGCThreads
以原CPU核数为1,变配后CPU核数为2的场景为例,如果Java默认的相关线程配置和推荐的配置差别较大,则可以修改Java应用的启动命令如下:
java -XX:ParallelGCThreads=2 -XX:ConcGCThreads=1 -XX:CICompilerCount=2 -jar app.jar