原文地址:https://blog.lanweihong.com/p...

前言

在微服务架构中,网关、注册核心、配置核心、服务追踪、认证核心等一系列组件部署到服务器中会占用肯定的内存,还有各个业务服务,一部署单个服务可能就占个几百M,甚至上G。那这一系列组件和服务同时部署不得耗费更多的内存?为避免这些服务把系统资源耗尽导致宕机,咱们不得不为这些服务配置肯定的内存限度。

在 k8s 环境中,如果咱们单单配置了 memory 的 limit ,没有配置 Java 利用的JVM参数,那么在 Java 程序运行过程中可能会导致内存超过 memory 的 limit ,发送 OOM 谬误。因而,部署Java 利用到 k8s 环境中时要配置JVM参数及k8s的 memory limit。

JVM 参数配置办法

随着JAVA版本不同,有不同的解决办法,如下表:

JDK版本JVM参数
<8u131-Xms64m -Xmx128m
8u131-191-XX:+UnlockExperimentalVMOptions-XX:+UseCGroupMemoryLimitForHeap
>8u191-XX:UseContainerSupport(默认启用)、ActiveProcessorCount;百分比调配堆内存:MaxRAMPercentageInitialRAMPercentageMinRAMPercentage

JDK8版本小于131时,启动JAVA程序时,增加参数 -Xms64m -Xmx128m;java 8u131+和java 9+版本,增加两个参数:-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap;JDK8版本高于191时,能够应用 MaxRAMPercentageMaxRAMPercentage 值介于 0.0 到 100.0 之间,默认值为 25.0。

配置

JDK版本8u131

Dockerfile 文件中配置:

ENV JVM_OPTS -Xms256m -Xmx512mENTRYPOINT exec java $JVM_OPTS -jar lanweihong.jar

留神这两个参数只设置了调配给堆的大小,理论的memory limit应该比这个还要大。

java 8u131+和java 9+版本

对于java 8u131+和java 9+版本,在 Dockerfile 文件中,设置环境变量:

ENV JVM_OPTS -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=2ENTRYPOINT exec java $JVM_OPTS -jar lanweihong.jar

其中 -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap 设置 -XX:MaxRAM 为 cgroup 的内存限度,这里的-XX:MaxRAMFraction 值为 2,那么 JVM 容许调配的内存为 MaxRAM / MaxRAMFraction = 4G / 2 = 2G,不设置为 1 是避免JVM占用所有的内存,导致其余过程(如Shell、MySQL等)没有可用内存。

JDK版本 8u191+

Dockerfile 文件中配置:

ENV JVM_OPTS -XX:MaxRAMPercentage=80.0ENTRYPOINT exec java $JVM_OPTS -jar lanweihong.jar

设置 JVM 可用的内存为总内存的 80%,显然这种形式更加灵便不便,也更平安。

如果应用 jib-maven-plugin 打包的,能够在 pom.xml 中增加配置:

...<container>    <mainClass>com.lanweihong.gateway.GatewayApplication</mainClass>    <!-- 增加 jvm 参数 -->    <jvmFlags>        <jvmFlag>-XX:MaxRAMPercentage=80.0</jvmFlag>    </jvmFlags></container>...

执行成果等同于 java -XX:MaxRAMPercentage=80.0 ...

k8s 配置

设置内存 limit;在 k8s 部署配置文件增加:

containers:    resources:      requests:        memory: "512Mi"        # cpu: "500m"      limits:        memory: "512Mi"        # cpu: "500m"    env:      - name: JVM_OPTS        values: -XX:MaxRAMPercentage=80.0

应用 kubectl apply -f 更新公布服务。

总结

  1. JDK8版本低于191的倡议降级到最新版本,或191当前,Java 8u191和Java 10+ 反对 UserContainerSupport,设置JVM启动参数 MaxRAMPercentage,具体的值依据状况来设置;
  2. 不降级JDK版本的,依据JDK版本按以上阐明配置;
  3. Kubernetes 配置 Limit。

参考文档

  1. How To Configure Java Heap Size Inside a Docker Container
  2. Kubernetes_pod_javajdk_动静JVM堆内存大小限度