使用 VisualVM 通过 Kubernetes 集群后面的 JMX 监控 dockerised Spring Boot 应用程序内部

Posted

技术标签:

【中文标题】使用 VisualVM 通过 Kubernetes 集群后面的 JMX 监控 dockerised Spring Boot 应用程序内部【英文标题】:Monitor dockerised Spring Boot application internals via JMX behind a Kubernetes cluster with VisualVM 【发布时间】:2020-10-03 15:18:16 【问题描述】:

我想在 Docker 中为我的 Spring Boot 应用程序监控 JVM 的内部结构,该应用程序在 Kubernetes 集群中作为 pod 运行。但是即使花费了相当长的时间,我也无法在任何地方找到令人满意的答案。 我尝试在this 上引用已接受的答案,但它仅在我的 docker 在本地运行时才连接,并且在 Kubernetes 集群后面时停止连接。

【问题讨论】:

【参考方案1】:

假设我想在我的应用在 8000 上提供服务时在端口 8001 上进行监控。 在本地运行 Docker 并将端口 8001 从我的本地映射到 Docker(-p 8001:8001)

-Dcom.sun.management.jmxremote \
-Djava.rmi.server.hostname=localhost \
-Dcom.sun.management.jmxremote.port=8001 \
-Dcom.sun.management.jmxremote.rmi.port=8001 \
-Dcom.sun.management.jmxremote.local.only=false \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false

但它不适用于远程 Kubernetes 集群中的 pod。我找到了this,但我的要求是在不通过服务的情况下进行监控,然后通过阅读其他几篇文章我得到了它的工作,因此整理以下这些步骤以节省某人的时间:-

    删除了上述启动脚本中提到的 VM 选项 更新了我的 application.yaml,如下所示,我启用了 jmx 并添加了运行 JMXMP 连接器服务器的 url
spring:
  application:
    name: stack-application
  jmx:
    enabled: true
    url: service:jmx:jmxmp://localhost:8001/
server:
  port: 8000
    将部署块下的 Kubernetes 部署 YAML 更新为:
apiVersion: apps/v1
kind: Deployment
----your content----
          ports:
            - name: stack-app-port
              containerPort: 8000
            - name: stack-jmx-port
              containerPort: 8001
    在我的 pom.xml 中添加了以下依赖项,用于下载 JMXMP,因为经过研究后我得出结论,通过 RMI 进行 JMX 监控是一项艰巨的工作,因此每个人都建议使用 JMXMP。
        <dependency>
            <groupId>org.glassfish.main.external</groupId>
            <artifactId>jmxremote_optional-repackaged</artifactId>
            <version>5.0</version>
        </dependency>
    创建了一个新类 ConnectorServiceFactoryBeanProvider,它从我们的 application.yaml 中获取 URL
@Configuration
public class ConnectorServiceFactoryBeanProvider 
    @Value("$spring.jmx.url")
    private String url;

    @Bean
    public ConnectorServerFactoryBean connectorServerFactoryBean() throws Exception 
        final ConnectorServerFactoryBean connectorServerFactoryBean = new ConnectorServerFactoryBean();
        connectorServerFactoryBean.setServiceUrl(url);
        return connectorServerFactoryBean;
    

    在 Kubernetes 上构建和部署您的 docker,并找出 pod 的 IP 地址。您可以在 CLI 上使用 kubectl describe pod 现在要启动 VisualVM,我们还需要将上面下载的 JMXMP jar 添加到类路径中。我创建了一个别名来做同样的事情,因为 JAR 是在我的本地 .m2 目录中下载的,所以命令看起来像这样:-
alias viz='jvisualvm -cp "$JAVA_HOME:~/.m2/repository/org/glassfish/main/external/jmxremote_optional-repackaged/5.0/jmxremote_optional-repackaged-5.0.jar"'
    现在,执行“viz”或您的别名,它将启动 Java 附带的 Visual VM 应用程序。 点击VisualVM工具栏中的+JMX图标或转到(文件->添加JMX连接...)添加链接
service:jmx:jmxmp://<IP address obtained in step 6 above>:8001

并选中“不需要 SSL 连接”。点击 OK 后,您应该会在一段时间后在 VisualVM 上看到您的远程应用程序内部结构。下面附上截图。

VisualVM screenshot monitoring remote app on 8001

【讨论】:

太好了,这是我在任何地方都能找到的唯一解决方案。非常感谢!

以上是关于使用 VisualVM 通过 Kubernetes 集群后面的 JMX 监控 dockerised Spring Boot 应用程序内部的主要内容,如果未能解决你的问题,请参考以下文章

OutOfMemory 异常 - VisualVM 如何通过 heapdump 文件帮助定位内存泄漏?

VisualVM通过JMX远程连接JVM

visualvm 可以通过 JMX 自动连接到远程进程吗?

使用 VisualVM 分析 tomcat 应用程序

VisualVM工具的使用

VisualVM初次使用BTrace功能方法步骤