容器环境 JVM 内存动态配置

标签: 系统运维 | 发表时间:2021-09-26 11:53 | 作者:树辉
出处:https://vqiu.cn/
容器环境 JVM 内存动态配置

  在微服务架构中, JAVA 框架占用了绝大部分的市场,比如 Spring CloudDubbo等,其中在使用容器化部署的时候经常碰到关于JVM的内存分配的大小的配置,以下来讲述自己所用到过的配置方式。

固定配置

此方式,顾名思义,就是将JVM参数进行固定化,比如在将JAR打包成容器镜像时

  FROM openjdk:8-jdk-alpine
LABEL maintainer="Shuhui<[email protected]>"

RUN set -xe \
    && sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
    && apk update \
    && apk add --no-cache ca-certificates ttf-dejavu fontconfig tzdata tini \
    && cp -rf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
    && echo "Asia/Shanghai" > /etc/timezone

COPY app.jar /
VOLUME ["/apps/logs"]

ENTRYPOINT ["/sbin/tini", "--", "java", "-jar", "-Xms1g", "-Xmx2g", "/scheduler.jar"]

可以看到,在容器运行时将JVM参数固定死了,也就是后续需要改动的话需要重新操作镜像。Em。。。 这种牵一发动全身的方式不可取。不推荐使用

环境变量

环境变量的方式可理解为固定配置的升级版本,就是将JVM参数包装成一个专用的环境变量,比如" JAVA_OPTS":

  FROM openjdk:8-jdk-alpine
LABEL maintainer="Shuhui<[email protected]>"

RUN set -xe \
    && sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
    && apk update \
    && apk add --no-cache ca-certificates ttf-dejavu fontconfig tzdata tini \
    && cp -rf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
    && echo "Asia/Shanghai" > /etc/timezone

ENV JAVA_OPTS "-server -Xms1024m -Xmx2048m"

COPY app.jar /
VOLUME ["/apps/logs"]

ENTRYPOINT exec /sbin/tini -- java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar /app.jar

JVM参数直接引用一个叫 JAVA_OPTS的环境变量,后续需要改动时直接改动这个参数即可,比如,使用 configmap的方式:

  $ cat xx-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: xx-config
data:
  JAVA_OPTS: '-Xms1024m -Xmx2048m'

编排文件中引入

        containers:
      - image: #IMAGE_NAME#:#IMAGE_TAG#
        name: xx
        imagePullPolicy: IfNotPresent
        env:
        - name: JAVA_OPTS
          valueFrom:
            configMapKeyRef:
              name: xx-config
              key: JAVA_OPTS

当然,若你跟我一样,不喜欢套来套去--嫌弃使用 configmap繁琐,直接传参亦可:

          env:
        - name: JAVA_OPTS
          value: "-server -Xms2048m -Xmx4096m -Djava.security.egd=file:/dev/./urandom -Duser.timezone=GMT+08"

动态分配

jdk1.8.191的版本新增了以下 JVM参数,可以按容器所分配的内存资源大小去动态分配,我们无须去固定指定为个值的大小,这也是目前比较合理的一种方式,同时也是推荐的一种方式。。

参数 说明
-XX:InitialRAMPercentage=N 将初始堆大小设置为总内存的百分比
-XX:MinRAMPercentage=N 将最小堆大小设置为总内存的百分比
-XX:MaxRAMPercentage=N 将最大堆大小设置为总内存的百分比

提示: 如果已经配置了 -Xms, 那么 -XX:InitialRAMPercentage 参数将忽略,如果已经配置了 Xmx ,那么 -XX:MaxRAMPercentage 参数将忽略.

如果应用程序在容器中运行,并且指定了 -XX:+UseContainerSupport,则容器的默认堆大小(默认4分1的内存容量)。

示例: 通用的启动脚本中指定80%( -XX:MaxRAMPercentage=80.0 -XX:InitialRAMPercentage=80.0 -XX:MinRAMPercentage=80.0)。那么以pod为1G的内存为例,服务就相当于设置了 -Xmx819m -Xms819m

  • Dockerfile 范例如下:
  FROM openjdk:8-jdk-alpine
LABEL maintainer="Qiu Shuhui<[email protected]>"

ARG user=shuhui
ARG group=shuhui
ARG uid=1000
ARG gid=1000
ARG APP_HOME=/app

ENV APP_HOME $APP_HOME
ENV JAVA_OPTS "-server -Djava.security.egd=file:/dev/./urandom"

RUN set -xe \
    && sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
    && apk update upgrade \
    && apk add --no-cache procps ca-certificates ttf-dejavu fontconfig curl tzdata tini bash \
    && cp -rf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
    && echo "Asia/Shanghai" > /etc/timezone \
    && rm -rf /var/cache/apk/*

RUN set -xe \
    && mkdir -p $APP_HOME \
    && chown ${uid}:${gid} $APP_HOME \
    && addgroup -g ${gid} ${group} \
    && adduser -h "$APP_HOME" -u ${uid} -G ${group} -s /bin/bash -D ${user}

COPY --chown=$user xx.jar $APP_HOME/app.jar

USER $uid
WORKDIR $APP_HOME


ENTRYPOINT ["/sbin/tini", "--"]
CMD ["java -XX:InitialRAMPercentage=80.0 -XX:MinRAMPercentage=80.0 -XX:MaxRAMPercentage=80.0 -jar /app.jar"]

此后,访问容器无需再设置 Xmx为固定值,随着CGroup的资源去动态分配。

参考引用

相关 [容器 环境 jvm] 推荐:

容器环境 JVM 内存动态配置

- - 枯惠
  在微服务架构中, JAVA 框架占用了绝大部分的市场,比如 Spring Cloud、 Dubbo等,其中在使用容器化部署的时候经常碰到关于JVM的内存分配的大小的配置,以下来讲述自己所用到过的配置方式. 此方式,顾名思义,就是将JVM参数进行固定化,比如在将JAR打包成容器镜像时. 可以看到,在容器运行时将JVM参数固定死了,也就是后续需要改动的话需要重新操作镜像.

容器环境的JVM内存设置最佳实践 - JadePeng - 博客园

- -
Docker和K8S的兴起,很多服务已经运行在容器环境,对于java程序,JVM设置是一个重要的环节. 这里总结下我们项目里的最佳实践. 默认情况下,jvm自动分配的heap大小取决于机器配置,比如我们到一台64G内存服务器:. 可以看到,JVM 分配的最大MaxHeapSize为 16G,计算公式如下:.

Tomcat7调优及JVM性能优化for Linux环境

- - 互联网 - ITeye博客
该优化针对Linux X86_X64环境. Tomcat优化其实就是对server.xml优化(开户线程池,调整http connector参数). 搜索【

在生产环境运行容器

- - IT瘾-tuicool
【编者的话】Vivek Juneja是一名工作首尔的云服务工程师. 他从2008年就开始接触云服务,是最早的AWS和Eucalyptus的使用者. 本文中总结了在生产环境中使用容器的几个方面,特别是对虚拟机与容器的混合部署的观点很值得推荐给大家. 如果只是把容器限制在开发测试环境中,那么您并没有享受到面向容器研发和发布工作的全部红利.

JVM研究

- - 开源软件 - ITeye博客
每天接客户的电话都是战战兢兢的,生怕再出什么幺蛾子了. 我想Java做的久一点的都有这样的经历,那这些问题的最终根结是在哪呢. JVM全称是Java Virtual Machine,Java虚拟机,也就是在计算机上再虚拟一个计算机,这和我们使用 VMWare不一样,那个虚拟的东西你是可以看到的,这个JVM你是看不到的,它存在内存中.

jvm调优

- - 互联网 - ITeye博客
printf "%x\n" 21742  找到耗时最长的进程. jstack pid | grep 54ee  定位某个类的方法. jstack 10535|grep -A 10 2a1d (最后十行). jmap 查询pid 内存线程. 附:TOP命令中需要关注的值:. (1)load average:此值反映了任务队列的平均长度;如果此值超过了CPU数量,则表示当前CPU数量不足以处理任务,负载过高.

学习JVM的References

- LightingMan - 淘宝JAVA中间件团队博客
本blog中列举了我学习JVM的references,会不断的更新,为了避免版权问题,就不在blog上提供references的下载了,感兴趣的同学可自行下载或购买,:). |— [ Hotspot GC论文 ]. |— [ 其他JVM GC ]. |— Linux内核源代码情景分析. |— Linux 内核中断内幕.

深入理解JVM

- 小伟 - ITeye论坛最新讨论
1   Java技术与Java虚拟机. 说起Java,人们首先想到的是Java编程语言,然而事实上,Java是一种技术,它由四方面组成: Java编程语言、Java类文件格式、Java虚拟机和Java应用程序接口(Java API). 图1   Java四个方面的关系. 运行期环境代表着Java平台,开发人员编写Java代码(.java文件),然后将之编译成字节码(.class文件).

jvm垃圾回收

- Cano - 淘宝共享数据平台 tbdata.org
在jvm中堆空间划分为三个代:年轻代(Young Generation)、年老代(Old Generation)和永久代(Permanent Generation). 年轻代和年老代是存储动态产生的对象. 永久带主要是存储的是java的类信息,包括解析得到的方法、属性、字段等等. 我们这里讨论的垃圾回收主要是针对年轻代和年老代.

JVM内存分配

- - 移动开发 - ITeye博客
计算机内存,它算是CPU与计算机打交道最频繁的区域,所有数据都是先经过硬盘至内存,然后由CPU再从内存中获取数据进行处理,又将数据保存到内存,通过分页或分片技术将内存中的数据再flush至硬盘. 那JVM的内存结构到底是如何呢. JVM做为一个运行在操作系统上,但又独立于os运行的平台,它的内存至少应该包括象寄存器、堆栈等区域.