为 Azure 容器应用中的 Java 应用高效使用内存

Java 虚拟机 (JVM) 保守地使用内存,因为它假设操作系统内存必须在多个应用程序之间共享。 但是,你的容器应用可以优化内存使用情况,并为应用提供尽可能多的可用内存。 此内存优化称为 Java 自动内存拟合。 启用内存调整后,Java 应用性能通常会提高 10% 到 20%,而无需更改任何代码。

Azure 容器应用在以下情况下支持自动内存拟合:

  • 单个 Java 应用在容器中运行。
  • 应用程序部署自源代码或 JAR 文件。

默认情况下启用自动内存拟合,但可以手动禁用。

禁用内存拟合

大多数情况下,自动内存拟合非常有用,但这可能并非适用于所有情况。 可以手动或自动禁用内存拟合。

手动禁用

若要在创建容器应用时禁用内存拟合,请将环境变量 BP_JVM_FIT 设置为 false

以下示例演示了如何通过 createupupdate 命令禁用内存拟合。

az containerapp create \
  --name <CONTAINER_APP_NAME> \
  --resource-group <RESOURCE_GROUP> \
  --image <CONTAINER_IMAGE_LOCATION> \
  --environment <ENVIRONMENT_NAME> \
  --env-vars BP_JVM_FIT="false" 

若要验证是否已禁用内存拟合,请检查日志中是否有以下消息:

禁用 jvm 内存拟合,原因:手动禁用

自动禁用

满足以下任一条件时,系统会自动禁用内存拟合:

  • 容器内存有限:容器内存小于 1 GB。

  • 明确设置内存选项:通过 JAVA_TOOL_OPTIONS 在环境变量中指定一项或多项内存设置时。 内存设置选项包括以下值:

    • -XX:MaxRAMPercentage
    • -XX:MinRAMPercentage
    • -XX:InitialRAMPercentage
    • -XX:MaxMetaspaceSize
    • -XX:MetaspaceSize
    • -XX:ReservedCodeCacheSize
    • -XX:MaxDirectMemorySize
    • -Xmx
    • -Xms
    • -Xss

    例如,如果已在环境变量中指定最大堆大小,则会自动禁用内存拟合,如下例所示:

    az containerapp update \
      --name <CONTAINER_APP_NAME> \
      --resource-group <RESOURCE_GROUP> \
      --image <CONTAINER_IMAGE_LOCATION>  \
      --set-env-vars JAVA_TOOL_OPTIONS="-Xmx512m" 
    

    禁用内存拟合后,会在记录中看到以下消息输出:

    禁用 jvm 内存拟合,原因:使用 JAVA_TOOL_OPTIONS=-Xmx512m 中指定的设置,而不是选取 JAVA_TOOL_OPTIONS: -Xmx512m

  • 小型非堆内存大小:在极少数情况下,计算出的堆或非堆大小太小(小于 200 MB)。

验证是否已启用内存

在启动期间检查日志流中是否存在引用计算的 JVM 内存配置的消息。

下面是启动期间的消息输出示例。

计算的 JVM 内存配置:-XX:MaxDirectMemorySize=10M -Xmx1498277K -XX:MaxMetaspaceSize=86874K -XX:ReservedCodeCacheSize=240M -Xss1M(总内存:2G,线程计数:250,已加载类计数:12924,空余空间:0%)

选取 JAVA_TOOL_OPTIONS:-XX:MaxDirectMemorySize=10M -Xmx1498277K -XX:MaxMetaspaceSize=86874K -XX:ReservedCodeCacheSize=240M -Xss1M

运行时配置

可以设置环境变量以影响内存拟合行为。

变量 Unit 示例 说明
BPL_JVM_HEAD_ROOM 百分比 BPL_JVM_HEAD_ROOM=5 根据给定的百分比为系统保留内存空间。
BPL_JVM_THREAD_COUNT Number BPL_JVM_THREAD_COUNT=200 预估的最大线程数。
BPL_JVM_CLASS_ADJUSTMENT Number
百分比
BPL_JVM_CLASS_ADJUSTMENT=10000
BPL_JVM_CLASS_ADJUSTMENT="10%"
按明确值或百分比调整 JVM 类计数。

注意

更改这些变量不会禁用自动内存拟合。

内存不足警告

如果你决定自行配置内存设置,则可能会遇到内存不足警告的风险。

下面是容器可能耗尽内存的一些可能原因:

  • 堆内存大于可用内存总量。

  • 非堆内存大于可用内存总量。

  • 堆 + 非堆内存大于可用内存总量。

在容器内存不足的情况下会遇到以下警告:

OOM 警告:堆内存 1200M 大于可用于分配 (-Xmx1200M) 的 1G 大小