Java应用启动加速的JVM参数配置

通过配置通用Java Virtual Machine(JVM)的垃圾回收机制(Garbage Collection Mechanism)和Just-In-Time(JIT)参数,能够更好地在Java应用启动过程中使用ACS的柔性变配能力。本文介绍和Java应用启动加速相关的ParallelGCThreadsConcGCThreadsCICompilerCount三个JVM参数的推荐配置方法。

背景介绍

Java应用在启动阶段需要经历类加载、字节码编译和优化的阶段,这个阶段对于一些复杂的应用而言,可能要持续几分钟甚至十几分钟的时间。通常在这个阶段Java应用占用了超过一半的资源执行非应用代码的加载、编译的逻辑。而在应用预热完成进入稳定运行态后,这些资源会处于空闲状态。因此您可以通过ACS的柔性算力变配能力,在Java应用启动时提供更多的算力来加速应用启动。

在JVM虚拟机中普遍存在编译线程、用户进程和垃圾回收线程,这些线程会在Java应用启动以及稳定运行的不同阶段,以不同的比例共同占据整个Java应用的资源。 为了使Java应用能更好地发挥应用启动加速的效益,同时保证Java稳态运行时的性能,需要根据业务自身的特征,调整JVM参数配置从而合理地分配线程资源。

image

变配相关JVM参数推荐配置

下面将重点介绍和应用启动加速相关的3个重要JVM参数:ParallelGCThreadsConcGCThreadsCICompilerCount,以及它们的推荐配置参数。

假设用户程序设置的实际CPU核数是,同时使用ACS的CPU柔性变配能力之后,实际应用启动阶段所获得的算力核数是)。整体而言, 上述3个JVM线程参数应设置的足够大, 从而更好地使用额外增加的()核算力;同时考虑在启动加速时间之后核数会被降到的情况, 应避免设置参数过大,并保证变配能持续到应用基本完成预热, 否则会导致应用线程无法获得足够的CPU资源而影响应用线程性能。

JVM参数

参数说明

推荐配置参数

ParallelGCThreads

并行GC的线程数。表示并行垃圾回收器使用的线程数量。

核,配置-XX:ParallelGCThreads=Y

则配置-XX:ParallelGCThreads=

ConcGCThreads

并发GC的线程数。这些线程与应用程序线程并发运行,以减少停顿时间,所以需要给业务线程保留足够的线程数资源。

配置值计算方法-XX:ConcGCThreads=,即四分之一的并行GC线程数。

CICompilerCount

JIT编译线程数。此数值与程序的执行效率相关。频繁的JIT编译可能会导致性能瓶颈,因此不合理的JIT编译线程数会影响程序的执行效率。若配置过少的JIT线程数,因为解释执行效率较低的原因,可能会导致方法执行慢并且占用过高的CPU资源。

变配后CPU核数(值)

CICompilerCount参考值

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