如何用Cryostat监控Quarkus JVM模式

279 阅读4分钟

用Cryostat监控Quarkus JVM模式

Cryostat是一个剖析和监控工具,它利用了已经存在于HotSpot JVM上运行的Java应用程序中的JDK Flight Recorder(JFR)框架。Cryostat提供了一个集群内的收集中心,以便从集群外轻松、安全地访问你的JDK飞行记录器数据。Cryostat是一个云原生应用程序,主要针对OpenShift上的部署,所以本指南将假设你也将你的Quarkus应用程序部署到OpenShift上,以示简单。

在这篇文章中,我们将探讨如何配置Quarkus应用程序以允许Cryostat连接到它们,使Cryostat能够与Quarkus通信并提供其JDK飞行记录器的收集、存储和分析工具。

Automated Analysis Report in the Cryostat web-client UI

图1.Cryostat自动分析报告

Grafana dashboard displaying metrics from Cryostat

图2.Cryostat Grafana仪表板

使用Quarkus的Cryostat的注意事项

Quarkus具有标准JVM模式(构建产生.JAR文件,在运行时由JVM加载和运行)或本地模式(构建产生本地二进制文件,直接执行)的能力。Cryostat依赖于JDK Flight Recorder(JFR)和JDK Management Extensions(JMX),前者在Quarkus本地模式下只得到部分支持,后者在撰写本文时不支持本地模式。这意味着,不幸的是,只有JVM模式的Quarkus应用程序可以被配置为Cryostat使用。

开始使用Cryostat

在OpenShift上开始使用Cryostat是快速而简单的,只需从OperatorHub上安装即可。

Cryostat Operator in the OpenShift OperatorHub

图 3.安装Cryostat

然后创建一个Cryostat CR资源实例,让操作员知道你想部署一个Cryostat实例。在这个阶段,您还可以选择一些配置选项,但我们现在先假设默认值。

A created Cryostat CR in the OpenShift Console

图4.创建低温恒温器

Cryostat通信

Cryostat使用JMX来与运行在HotSpot JVM上的应用程序对话,包括但不限于Java和Scala应用程序。JMX是一种标准的Java技术,它允许工具连接到应用程序,并通过各种底层传输协议执行操作或检索数据。如果你在JVM模式下构建和部署你的Quarkus应用程序,那么JMX支持已经内置并准备好开箱即用。有两种方法可以在你的应用程序上启用JMX。

方法1:在运行时启用

JMX可以通过设置JVM系统属性来启用。

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=${RJMX_PORT}
-Dcom.sun.management.jmxremote.rmi.port=${RJMX_PORT}
-Djava.rmi.server.hostname=127.0.0.1
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.local.only=false

其中${RJMX_PORT} ,用你选择的端口号代替,以便通过RMI进行远程JMX网络连接。在这个例子中,我们禁用了JMX认证和JMX SSL--在实践中,出于安全考虑,这些都应该被启用,但配置这些特定的选项不在本指南的范围内。更多信息请参见本文档

Quarkus使用了一个功能丰富的应用程序启动脚本,它允许我们在运行时通过简单设置环境变量来添加JVM系统属性。

JAVA_OPTS_APPEND="-Dcom.sun.management.jmxremote -
Dcom.sun.management.jmxremote.port=${RJMX_PORT} -
Dcom.sun.management.jmxremote.rmi.port=${RJMX_PORT}
-Djava.rmi.server.hostname=127.0.0.1 
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.local.only=false"

如果你在OpenShift或Kubernetes中运行你的Quarkus应用程序,那么请尝试在你的DeploymentDeploymentConfig ,嵌套在应用程序的Spec ,设置这个环境变量Container 。这种启用JMX的方法不需要重建Quarkus应用,只需要重新部署。

方法2:在构建时启用

通过编辑src/main/docker/ 下的Dockerfile.jvm ,可以将与之前相同的JVM系统属性添加到容器化Quarkus应用程序中。下面是一个来自基本Quarkus项目的样本Dockerfile.jvm - 注意已经添加的ENV JAVA_OPTS_APPEND 行,以附加JVM属性并暴露端口号。

FROM registry.access.redhat.com/ubi8/openjdk-11:1.11

ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'


# We make four distinct layers so if there are application changes the library layers can be re-used
COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/
COPY --chown=185 target/quarkus-app/*.jar /deployments/
COPY --chown=185 target/quarkus-app/app/ /deployments/app/
COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/

EXPOSE 8080 ${RJMX_PORT}
USER 185
ENV JAVA_OPTS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
ENV JAVA_OPTS_APPEND="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=${RJMX_PORT} -Dcom.sun.management.jmxremote.rmi.port=${RJMX_PORT} -Djava.rmi.server.hostname=127.0.0.1 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.local.only=false"
ENV JAVA_APP_JAR="/deployments/quarkus-run.jar"

同样,要确保在这个文件中用端口号替换所有行的${RJMX_PORT}

这种方法不太灵活,因为它要求在构建时就知道远程JMX端口号,而且需要重建和重新部署应用程序。

Cryostat发现

现在我们已经在Quarkus应用程序上启用了JMX并重新部署了它,它已经准备好与Cryostat对话。然而,在这之前,Cryostat需要知道如何以及在哪里找到该应用程序。有两种方法可以实现这一点:自动发现和自定义目标。自动发现是首选方法,默认情况下是启用的。自定义目标可用于填补部署的应用程序目标的空白,这些目标不符合自动发现的标准,但已知可通过网络到达。

自动发现

Cryostat可以自动发现目标应用程序,并使用其发现的远程JMX服务URL进行连接。自动发现取决于部署平台--在撰写本文时,Cryostat在OpenShift/Kubernetes上部署时将使用OpenShift/Kubernetes API来发现Endpoints 。如果没有OpenShift/Kubernetes API服务器,那么Cryostat就会退回到使用Java发现协议(JDP)。在任何情况下,自动发现的目标都会与自定义目标合并。如果使用OpenShift/KubernetesEndpoints 发现,那么目标应用程序应该有一个相关的Service 对象,为集群内部的JMX流量暴露一个端口。该端口必须使用端口号9091或名称jfr-jmx ,以便Cryostat将其作为预期的目标应用程序。

自定义目标

这是一种让Cryostat客户(最终用户或其他自动化工具)告诉Cryostat如何以及在哪里找到单一目标应用程序实例的方法。自定义目标的核心是一个网络可到达的远程连接JMX URL和一个人类可读的别名。这些可以通过点击目标选择下拉菜单上的+ (Plus)图标或使用你喜欢的HTTP客户端在Cryostat网页客户端中创建。

curl \
  -X POST \
  -F alias=myapp \
  -F connectUrl=service:jmx:rmi:///jndi/rmi://myapp.my-openshift-cluster.example.com:1234/jmxrmi \
  https://cryostat.my-openshift-cluster.example.com/api/v2/targets

一旦添加了自定义目标定义,connectUrl ,就可以在Cryostat HTTP API中任何需要的地方作为targetId URL参数使用。

关于Cryostat的进一步信息,请参见以下链接: