4

从历史上看,HotSpot 在 docker 容器中运行的记录很差,错误地判断了分配的资源(例如 RAM)。不过,情况正在慢慢好转。

OpenJ9 如何与 docker 容器保持一致,以及它在多大程度上了解容器提供的资源(内存、套接字、线程等)

此外,在 JavaOne 2017 演示中提到 OpenJ9 可以跨不同的 OpenJ9 VM 缓存 jit 编译的类。当虚拟机被限制在不同的容器中时(或)如果容器化的 JVM 共享一个 docker 卷,这种共享缓存是否可能?

4

2 回答 2

2
  1. Container support is currently being worked on, for cgroup awareness, please check this PR. This will lead upto adding container support as well.
  2. With regards to the Shared Class Cache (SCC), both scenarios are possible. Please see "Using the Class Data Sharing feature" from here for an example of sharing a docker volume. When the JVMs are confined to different containers with no shared volume, it is recommended to build the docker container with the SCC pre-built. You dockerfile will look like this.

    FROM adoptopenjdk/openjdk9-openj9:x86_64-alpine-jdk-9.181

    RUN mkdir /opt/shareclasses && mkdir /opt/app

    COPY japp.jar /opt/app

    CMD ["java", "-Xshareclasses:cacheDir=/opt/shareclasses", "-jar", "/opt/app/japp.jar"]

You would then need to build and run the image and commit the resultant container and make that as your base image.

docker build -t japp:latest . docker run japp docker commit container_id japp

于 2017-10-17T08:16:54.340 回答
0

可以创建共享类缓存并将其包含在 Docker 文件中。

共享类缓存可以在开发或预生产环境中创建,或者在应用程序上运行一些测试时创建。在 Pre-prod 中创建缓存可能更有效在构建过程中通过测试来实现它要简单得多。我使用 Spring Boot 应用程序对其进行了测试,即使是任何新生成的 Spring Boot 项目中包含的简单“contextLoads”测试也会产生巨大的差异

这是一个使用 Maven 进行测试的示例,但相同的 VM 选项也可以用于不同的场景。

1. 在启用共享类缓存的情况下运行测试

您可以使用 Surefire 插件在 Maven 中完成此操作,我不确定如何使用 Gradle 完成此操作

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <configuration>
    <argLine>-Xquickstart -Xshareclasses:cacheDir=classCache,name=appname -Xscmx32m </argLine>
  </configuration>
</plugin>

虚拟机参数:-Xquickstart -Xshareclasses:cacheDir=classCache,name=appname -Xscmx32m

  • cacheDir子选项用于指定缓存文件夹,以便更容易包含在 Docker 映像中
  • 名称子选项是为了避免难以预测的自动缓存名称
  • -Xscmx选项用于限制缓存大小,这应该针对应用程序进行调整,在启动速度和图像大小之间进行权衡
  • -Xquickstart选项指示 JVM 在与 -Xshareclasses 选项结合使用时执行尽可能多的 AOT

您可以检查printStats subOption 使用了多少缓存大小,如下所示: java -jar -Xshareclasses:cacheDir=classCache,name=appname,readonly, printStats application.jar

2. 将预热缓存添加到 Docker 镜像

在这种情况下,只需将 cacheDir 子选项设置的目录添加到图像中 classCache

ADD classCache classCache

由于这些文件每次都会更改,因此应将 classCache 最后添加到图像中

使用缓存运行应用程序

ENTRYPOINT exec java -Xquickstart -Xtune:virtualized -Xshareclasses:cacheDir=classCache,name=appname,readonly -jar application.jar

虚拟机参数:-Xquickstart -Xtune:virtualized -Xshareclasses:cacheDir=classCache,name=appname,readonly -jar application.jar

可以使用classCache 和 name 子选项指定缓存,如果没有这些,JVM 可能会创建一个新的缓存文件夹并忽略添加到图像中的那个。

根据我的经验,readonly选项使它更快一点,但这并不是绝对必要的。因为当容器被销毁时这个缓存将被删除,所以没有必要持久化 canges。

-Xquickstart 和 -Xtune:virtualized选项可进一步优化容器中的启动速度

于 2019-08-12T20:49:56.900 回答