Java 服务 Docker 容器化优秀实践

网站建设3年前发布
45 0 0

2023030521141406168c521218be3cb0e7198361a827a1adaa8c415,当我们在容器中运行 Java 应用程序时,可能希望对其进行调整参数以充分利用资源。,在本教程中,我们将了解如何在运行 Java 进程的容器中设置 JVM 参数。本文将重点关注常见的 -Xmx 和-Xms 标志。,另外,我们还将研究使用某些 Java 版本运行的程序容器化的常见问题,以及如何在常见的容器化 Java 应用程序时设置自定义标志。,过去,JVM 不知道分配给容器的内存和 CPU。,Java 10 引入了一个新设置:+UseContainerSupport(默认启用)来修复 这个问题[3],并在 8u191[4] 中将修复反向移植到 Java 8 。,现在 JVM 可以根据分配给容器的内存计算其内存。,当不设置-Xmx和-Xmx参数时,JVM 会根据系统规格来调整堆大小。,看看堆大小:,输出结果如下:,我们看到 JVM 将其堆大小设置为可用 RAM 的大约 25%。在这个例子中,在一个 16GB 的系统上分配了 4GB。,出于测试目的,创建一个文件,名为PrintXmxXms.java,内容是以 MB 为单位打印堆大小,代码内容如下:,假设已经安装了 JDK,可以编译程序并运行:,在 16Gb RAM 的主机上,输出结果为:,下面,在容器中尝试一下。,在包含 PrintXmxXms.java 文件的文件夹中添加以下 Dockerfile:,这里使用的容器使用旧版本的 Java 8,它早于更新版本中可用的容器支持。构建镜像:,Dockerfile 中的 CMD 行是运行容器时默认执行的进程。由于没有提供-Xmx或-XmsJVM 标志,内存设置将是默认设置。,运行容器:,现在使用--memory=1g命令行标志将容器内存限制为 1GB:,输出完全相同。这证明旧的 JVM 没有遵守容器内存限制。,使用相同的测试程序,更改 Dockerfile 的第一行来使用 JVM 8 的新版本:,然后再次做测试:,如上输出,使用整个 docker 主机内存来计算 JVM 堆大小。但是,如果为容器分配 1GB 的 RAM:,这一次,JVM 根据容器可用的 1GB RAM 计算堆大小。,现在我们了解了 JVM 如何计算其默认值以及为什么需要一个最新的 JVM 来获得正确的默认值。,与其直接在容器命令上硬编码 JVM 标志,不如使用环境变量。例如在Dockerfile 中使用 JAVA_OPTS 变量,可以在启动容器时对其进行修改:,构建镜像:,通过指定JAVA_OPTS环境变量在运行时选择内存设置:,注意:-Xmx 参数和 JVM 报告的 Max memory 之间存在细微差别。这是因为 Xmx 设置了内存分配池的最大大小,其中包括堆、垃圾收集器的幸存者空间和其他池。,Tomcat 9 容器有自己的启动脚本,因此要设置 JVM 参数,需要使用这些脚本。,bin/catalina.sh 脚本要求在环境变量 CATALINA_OPTS 中设置内存参数。,首先需要 创建一个 war 包 部署到 Tomcat。,然后,我们使用下面的Dockerfile 对其进行容器化,并在其中声明CATALINA_OPTS环境变量:,然后构建容器镜像并运行它:,注意:运行时,将新值传递给 CATALINA_OPTS。如果不提供这个值,会使用 Dockerfile 的第 3 行给出的默认值。,可以检查应用的运行时参数并验证选项-Xmx和-Xms是否存在:,Maven 和 Gradle 提供的插件允许我们在没有Dockerfile的情况下创建容器镜像。生成的镜像通常可以在运行时通过环境变量进行参数化。,下面看几个例子。,从 Spring Boot 2.3 开始,Spring Boot Maven 和 Gradle 插件可以在没有 Dockerfile 的情况下高效构建容器。,使用 Maven 时,将它们添加到 spring-boot-maven-plugin 中的 <configuration>块中:,要构建项目,运行下面的命令:,这将产生一个名为 <artifact-id>:<version> 的镜像。在这个例子中产生的镜像名为:demo-app:0.0.1-SNAPSHOT。Spring Boot 底层使用 Cloud Native Buildpacks 作为容器化技术。,该插件对 JVM 的内存设置进行硬编码。但是,我们仍然可以通过设置环境变量JAVA_OPTS 或 JAVA_TOOL_OPTIONS 来覆盖:,输出将与此类似:,就像 Spring Boot maven 插件一样,Google JIB 无需 Dockerfile 即可高效创建 Docker 镜像。Maven 和 Gradle 插件以类似的方式配置。Google JIB 还使用环境变量 JAVA_TOOL_OPTIONS 作为 JVM 参数的覆盖机制。,我们可以在任何能够生成可执行 jar 文件的 Java 框架中使用 Google JIB Maven 插件。例如,可以在 Spring Boot 应用程序中使用它来代替spring-boot-maven插件来生成容器镜像:,镜像是使用 mvn jib:dockerBuild 命令构建的:,尝试运行:,在本文中,我们介绍了需要使用最新的 JVM 来获取在容器中默认内存设置。,然后,研究了在自定义容器映像中设置 -Xms 和 -Xmx 的最佳实践, 以及如何使用现有 Java 应用程序容器在其中设置 JVM 选项。,最后,我们看到了如何利用构建工具来管理 Java 应用程序的容器化。,上面用到的 示例源代码 可在 ​​GitHub​​ 上获得。

© 版权声明

相关文章