欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

JMX和spring-boot-actuator入门

最编程 2024-02-07 16:33:23
...

想学习下spring-boot-actuator, 发现需要前置技能: JMX; 重新温习下JMX,并且根据spring官网对actuator进行quickstart

spring-boot-actuator源码

https://cloud.tencent.com/developer/article/1892726

官方文档

JMX官方demo

https://docs.oracle.com/javase/8/docs/technotes/guides/jmx/examples.html

spring-boot-actuator官方文档

https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.enabling

学习代码仓库

JMX代码示例及文档

https://gitee.com/eeaters/hogwarts/tree/master/jmx/src/main/java/com/caicai/study/jmxv2/mbean

https://gitee.com/eeaters/hogwarts/tree/master/jmx/src/main/java/com/caicai/study/jmxv2/managementFactory

以前不完整的学习代码: https://gitee.com/eeaters/hogwarts/tree/master/jmx

sping-boot-actuator官方文档示例及文档

https://gitee.com/eeaters/hogwarts/tree/master/spring-module/actuator

spring-boot-actuator与JMX总结

个人总结为:

JMX( Java Management Extension)是java的标准的管理拓展规范 , 日常工作中常用的系统监控,如:内存,cpu使用率,线程数,垃圾回收等监控曲线都可以通过jmx来进行管理;并且可以运行时动态修改配置

spring-boot-actuator: 是spring对jmx进行拓展, 个人目前认为改善有两点

- MBean虽然有标准/动态/模型/开放四种创建方式,但是代码编写有一定门槛,经过spring的封装后,可以通过注解的形式(内部大部分是扩展了ModelMBean)来进行MBean的创建,

- 默认情况下服务会使用rmi协议进行通讯, 但是rmi协议是JAVA的轻量级RPC通讯框架,对于非JVM虚拟机上的服务通讯上受限制,而现在中性的通讯框架大都选择http进行通讯, spring-boot-actuator就在原有的基础上支持http协议,

在gitee的文档外进行一些补充

MBeanServer

使用代码 MBeanServer server = ManagementFactory.getPlatformMBeanServer(); 创建一个MBeanServer时,默认恢将平台的默认组件添加进去, 诸如操作系统信息,类加载,jvm等信息都默认添加进去;

   public static synchronized MBeanServer getPlatformMBeanServer() {
        //...
        if (platformMBeanServer == null) {
            platformMBeanServer = MBeanServerFactory.createMBeanServer();
            for (PlatformComponent pc : PlatformComponent.values()) {
                List<? extends PlatformManagedObject> list =
                    pc.getMXBeans(pc.getMXBeanInterface());
                for (PlatformManagedObject o : list) {
                    if (!platformMBeanServer.isRegistered(o.getObjectName())) {
                        addMXBean(platformMBeanServer, o);
                    }
                }
            }
            //...
        return platformMBeanServer;
    }
enum PlatformComponent {
    CLASS_LOADING("java.lang.management.ClassLoadingMXBean", "java.lang", "ClassLoading", defaultKeyProperties(), true, new PlatformComponent.MXBeanFetcher<ClassLoadingMXBean>() {
        public List<ClassLoadingMXBean> getMXBeans() {
            return Collections.singletonList(ManagementFactoryHelper.getClassLoadingMXBean());
        }
    }, new PlatformComponent[0]),
    COMPILATION("java.lang.management.CompilationMXBean", "java.lang", "Compilation", defaultKeyProperties(), true, new PlatformComponent.MXBeanFetcher<CompilationMXBean>() {
        public List<CompilationMXBean> getMXBeans() {
            CompilationMXBean var1 = ManagementFactoryHelper.getCompilationMXBean();
            return var1 == null ? Collections.emptyList() : Collections.singletonList(var1);
        }
    }, new PlatformComponent[0]),
    MEMORY("java.lang.management.MemoryMXBean", "java.lang", "Memory", defaultKeyProperties(), true, new PlatformComponent.MXBeanFetcher<MemoryMXBean>() {
        public List<MemoryMXBean> getMXBeans() {
            return Collections.singletonList(ManagementFactoryHelper.getMemoryMXBean());
        }
    }, new PlatformComponent[0]),
    GARBAGE_COLLECTOR("java.lang.management.GarbageCollectorMXBean", "java.lang", "GarbageCollector", keyProperties("name"), false, new PlatformComponent.MXBeanFetcher<GarbageCollectorMXBean>() {
        public List<GarbageCollectorMXBean> getMXBeans() {
            return ManagementFactoryHelper.getGarbageCollectorMXBeans();
        }
    }, new PlatformComponent[0]),
    MEMORY_MANAGER("java.lang.management.MemoryManagerMXBean", "java.lang", "MemoryManager", keyProperties("name"), false, new PlatformComponent.MXBeanFetcher<MemoryManagerMXBean>() {
        public List<MemoryManagerMXBean> getMXBeans() {
            return ManagementFactoryHelper.getMemoryManagerMXBeans();
        }
    }, new PlatformComponent[]{GARBAGE_COLLECTOR}),
    MEMORY_POOL("java.lang.management.MemoryPoolMXBean", "java.lang", "MemoryPool", keyProperties("name"), false, new PlatformComponent.MXBeanFetcher<MemoryPoolMXBean>() {
        public List<MemoryPoolMXBean> getMXBeans() {
            return ManagementFactoryHelper.getMemoryPoolMXBeans();
        }
    }, new PlatformComponent[0]),
    OPERATING_SYSTEM("java.lang.management.OperatingSystemMXBean", "java.lang", "OperatingSystem", defaultKeyProperties(), true, new PlatformComponent.MXBeanFetcher<OperatingSystemMXBean>() {
        public List<OperatingSystemMXBean> getMXBeans() {
            return Collections.singletonList(ManagementFactoryHelper.getOperatingSystemMXBean());
        }
    }, new PlatformComponent[0]),
    RUNTIME("java.lang.management.RuntimeMXBean", "java.lang", "Runtime", defaultKeyProperties(), true, new PlatformComponent.MXBeanFetcher<RuntimeMXBean>() {
        public List<RuntimeMXBean> getMXBeans() {
            return Collections.singletonList(ManagementFactoryHelper.getRuntimeMXBean());
        }
    }, new PlatformComponent[0]),
    THREADING("java.lang.management.ThreadMXBean", "java.lang", "Threading", defaultKeyProperties(), true, new PlatformComponent.MXBeanFetcher<ThreadMXBean>() {
        public List<ThreadMXBean> getMXBeans() {
            return Collections.singletonList(ManagementFactoryHelper.getThreadMXBean());
        }
    }, new PlatformComponent[0]),
    LOGGING("java.lang.management.PlatformLoggingMXBean", "java.util.logging", "Logging", defaultKeyProperties(), true, new PlatformComponent.MXBeanFetcher<PlatformLoggingMXBean>() {
        public List<PlatformLoggingMXBean> getMXBeans() {
            PlatformLoggingMXBean var1 = ManagementFactoryHelper.getPlatformLoggingMXBean();
            return var1 == null ? Collections.emptyList() : Collections.singletonList(var1);
        }
    }, new PlatformComponent[0]),
    BUFFER_POOL("java.lang.management.BufferPoolMXBean", "java.nio", "BufferPool", keyProperties("name"), false, new PlatformComponent.MXBeanFetcher<BufferPoolMXBean>() {
        public List<BufferPoolMXBean> getMXBeans() {
            return ManagementFactoryHelper.getBufferPoolMXBeans();
        }
    }, new PlatformComponent[0]),
    SUN_GARBAGE_COLLECTOR("com.sun.management.GarbageCollectorMXBean", "java.lang", "GarbageCollector", keyProperties("name"), false, new PlatformComponent.MXBeanFetcher<com.sun.management.GarbageCollectorMXBean>() {
        public List<com.sun.management.GarbageCollectorMXBean> getMXBeans() {
            return PlatformComponent.getGcMXBeanList(com.sun.management.GarbageCollectorMXBean.class);
        }
    }, new PlatformComponent[0]),
    SUN_OPERATING_SYSTEM("com.sun.management.OperatingSystemMXBean", "java.lang", "OperatingSystem", defaultKeyProperties(), true, new PlatformComponent.MXBeanFetcher<com.sun.management.OperatingSystemMXBean>() {
        public List<com.sun.management.OperatingSystemMXBean> getMXBeans() {
            return PlatformComponent.getOSMXBeanList(com.sun.management.OperatingSystemMXBean.class);
        }
    }, new PlatformComponent[0]),
    SUN_UNIX_OPERATING_SYSTEM("com.sun.management.UnixOperatingSystemMXBean", "java.lang", "OperatingSystem", defaultKeyProperties(), true, new PlatformComponent.MXBeanFetcher<UnixOperatingSystemMXBean>() {
        public List<UnixOperatingSystemMXBean> getMXBeans() {
            return PlatformComponent.getOSMXBeanList(UnixOperatingSystemMXBean.class);
        }
    }, new PlatformComponent[0]),
    HOTSPOT_DIAGNOSTIC("com.sun.management.HotSpotDiagnosticMXBean", "com.sun.management", "HotSpotDiagnostic", defaultKeyProperties(), true, new PlatformComponent.MXBeanFetcher<HotSpotDiagnosticMXBean>() {
        public List<HotSpotDiagnosticMXBean> getMXBeans() {
            return Collections.singletonList(ManagementFactoryHelper.getDiagnosticMXBean());
        }
    }, new PlatformComponent[0]);

JMXServiceURL

JMXServiceURL类的注释有详细描述了暴露接口的格式,

/**
 * <p>The address of a JMX API connector server.  Instances of this class
 * are immutable.</p>
 *
 * <p>The address is an <em>Abstract Service URL</em> for SLP, as
 * defined in RFC 2609 and amended by RFC 3111.  It must look like
 * this:</p>
 *
 * <blockquote>
 *
 * <code>service:jmx:<em>protocol</em>:<em>sap</em></code>
 *
 * </blockquote>
 *
 * <p>Here, <code><em>protocol</em></code> is the transport
 * protocol to be used to connect to the connector server.  It is
 * a string of one or more ASCII characters, each of which is a
 * letter, a digit, or one of the characters <code>+</code> or
 * <code>-</code>.  The first character must be a letter.
 * Uppercase letters are converted into lowercase ones.</p>
 *
 * <p><code><em>sap</em></code> is the address at which the connector
 * server is found.  This address uses a subset of the syntax defined
 * by RFC 2609 for IP-based protocols.  It is a subset because the
 * <code>user@host</code> syntax is not supported.</p>
 *
 * <p>The other syntaxes defined by RFC 2609 are not currently
 * supported by this class.</p>
 *
 * <p>The supported syntax is:</p>
 *
 * <blockquote>
 *
 * <code>//<em>[host[</em>:<em>port]][url-path]</em></code>
 *
 * </blockquote>
 *
 * <p>Square brackets <code>[]</code> indicate optional parts of
 * the address.  Not all protocols will recognize all optional
 * parts.</p>
 *
 * <p>The <code><em>host</em></code> is a host name, an IPv4 numeric
 * host address, or an IPv6 numeric address enclosed in square
 * brackets.</p>
 *
 * <p>The <code><em>port</em></code> is a decimal port number.  0
 * means a default or anonymous port, depending on the protocol.</p>
 *
 * <p>The <code><em>host</em></code> and <code><em>port</em></code>
 * can be omitted.  The <code><em>port</em></code> cannot be supplied
 * without a <code><em>host</em></code>.</p>
 *
 * <p>The <code><em>url-path</em></code>, if any, begins with a slash
 * (<code>/</code>) or a semicolon (<code>;</code>) and continues to
 * the end of the address.  It can contain attributes using the
 * semicolon syntax specified in RFC 2609.  Those attributes are not
 * parsed by this class and incorrect attribute syntax is not
 * detected.</p>
 *
 * <p>Although it is legal according to RFC 2609 to have a
 * <code><em>url-path</em></code> that begins with a semicolon, not
 * all implementations of SLP allow it, so it is recommended to avoid
 * that syntax.</p>
 *
 * <p>Case is not significant in the initial
 * <code>service:jmx:<em>protocol</em></code> string or in the host
 * part of the address.  Depending on the protocol, case can be
 * significant in the <code><em>url-path</em></code>.</p>
 *
 * @see <a
 * href="http://www.ietf.org/rfc/rfc2609.txt">RFC 2609,
 * "Service Templates and <code>Service:</code> Schemes"</a>
 * @see <a
 * href="http://www.ietf.org/rfc/rfc3111.txt">RFC 3111,
 * "Service Location Protocol Modifications for IPv6"</a>
 *
 * @since 1.5
 */
public class JMXServiceURL implements Serializable {
}

rmi

rmi协议是java的轻量级的rpc协议,网上对此描述较多,定义可以自己查询,只是分析了下demo中的url;

首先jmx的规范服务url为: service:jmx:protocol:sap ,测试中是仿照网上的一篇博客编写, 直接对其进行简单的分析service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi 在JMXServiceURL构造参数中可以解析为:

  • requiredPrefix: service:jmx -- 这部分是固定的,不能有任何修改
  • protocol: rmi -- 协议: rmi协议
  • host: "" --主机地址是空的,因为协议后面跟的不是ip地址,
  • port: 0 -- host都为空,port不要想了
  • urlPath: /jndi/rmi://localhost:9999/jmxrmi -- url路径

MBean

标准MBean/MXBean

  • 对于标准MBean; 接口命名必须MBean为后缀,实现类就是接口去掉MBean
  • 对于标准MBean ; 注意接口和实现类放在同一个包下; MXBean没有此限制
  • MXBean使用接口方式对命名有限制,使用注解@MXBean则没有命名限制

ModelMBean

  • 仿照的是spring中的MBean来编写demo, 目前看springboot中大都是模型MBean

OpenMbean

  • 开放MBean,在一些spring对于rabbitmq/redis等提供支持时看到过部分使用; demo是基于硬编码的形式了解下openMBean的使用