原文地址: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 ;百分比分配堆内存:MaxRAMPercentage 、InitialRAMPercentage 、MinRAMPercentage |
JDK8版本小于131时,启动JAVA程序时,添加参数 -Xms64m -Xmx128m
;java 8u131+和java 9+版本,添加两个参数:-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
;JDK8版本高于191时,可以使用 MaxRAMPercentage
,MaxRAMPercentage
值介于 0.0 到 100.0 之间,默认值为 25.0。
配置
JDK版本8u131
在 Dockerfile
文件中配置:
ENV JVM_OPTS -Xms256m -Xmx512m
ENTRYPOINT 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=2
ENTRYPOINT 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.0
ENTRYPOINT 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
更新发布服务。
总结
- JDK8版本低于191的建议升级到最新版本,或191以后,Java 8u191和Java 10+ 支持
UserContainerSupport
,设置JVM启动参数MaxRAMPercentage
,具体的值根据情况来设置; - 不升级JDK版本的,根据JDK版本按以上说明配置;
- Kubernetes 配置 Limit。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。