为了便于理解,先简单介绍下我司的微服务。我司的微服务是以 Pod 的方式投递到 K8 环境中。Pod 中运行的是一个 springboot 项目。该项目是通过 Java 的 jar 命令来启动的,启动的同时设置了相关的 Xms 和 Xmx 等参数,如下:
jar -Xms$XMS -Xmx$XMX -Xmn$XMN /springboot-xxx.jar
对于 Pod 我们也做了一些相关的资源限制,如下:
在实际工作当中,由于 JVM 的 Xms、Xmx 和 Pod 的 resources.requests.memory、resources.limits.memory 都与内存相关,有一定的相关性,如果设置不好会出现一些问题。所以,如何设置,设置多大就成了不大不小的问题。
这里,我想强调下:
我这里只想提供一个较为无脑的通用配置方案,但在实际工作当中,还需要根据具体的情况具体设置。
在具体说配置原则之前,先说下我对 JVM 和 Pod 之间关系的理解:
首先通过 K8s 资源管理,圈定「Pod 中的容器」的资源范围,我们可以将这个过程视为攒一台指定配置(CPU、MEMORY)的电脑,我把 「Pod 中的容器」 类比为一台电脑,JVM 是一个运行在这台电脑上(Pod 中的容器)上的应用。为了保证这个电脑(Pod 中的容器)能够正常运行,其实还有很多无需我们关注的一些其他应用在运行。
通过,上边的理解,得出以下结论:
电脑(Pod 中的容器)的实际占用的内存 == JVM 占用的内存 + 其他应用占用的内存
我先把最终的通用配置方案抛出来,然后通过列出其他配置方案出现的问题,来说明为啥要这样,如下:
Xms == Xmx == resources.requests.memory < resources.limits.memory
其他配置组合如下:
这里 resources.requests.memory 可以理解为这些内存资源基本保证 Java 程序的日常运行。当 Java 程序某一时刻由于突发情况需要更多内存的时候(例如:并发高峰,定时任务等),此时, resources.limits.memory 参数将保证,该 Java 程序不会吃掉当前节点上的所有内存,进而影响其他应用的正常运行。