在Hibernate,EhCache,Quartz,DBCP和Spring中启用JMX

继续使用JMX的过程(请参阅: 人类JMX ),我们将学习如何在一些流行的框架中启用JMX支持(通常是统计和监视功能)。 这些信息大部分都可以在项目的主页上找到,但是我决定在收集这些信息的同时,很少添加一些有用的提示。

休眠(带有Spring支持)
使用JMX公开Hibernate统计信息非常简单 ,但是当使用JPA API获取基础SessionFactory时,需要一些讨厌的解决方法

class JmxLocalContainerEntityManagerFactoryBean() extends LocalContainerEntityManagerFactoryBean {
 override def createNativeEntityManagerFactory() = {
  val managerFactory = super.createNativeEntityManagerFactory()
  registerStatisticsMBean(managerFactory)
  managerFactory
 }

 def registerStatisticsMBean(managerFactory: EntityManagerFactory) {
  managerFactory match {
   case impl: EntityManagerFactoryImpl =>
    val mBean = new StatisticsService();
    mBean.setStatisticsEnabled(true)
    mBean.setSessionFactory(impl.getSessionFactory);
    val name = new ObjectName("org.hibernate:type=Statistics,application=spring-pitfalls")
    ManagementFactory.getPlatformMBeanServer.registerMBean(mBean, name);
   case _ =>
  }
 }

}

请注意,我已经创建了Springs内置LocalContainerEntityManagerFactoryBean的子类。 通过重写createNativeEntityManagerFactory()方法,我可以访问EntityManagerFactory并尝试将其向下转换为org.hibernate.ejb.EntityManagerFactoryImpl我们能够注册Hibernate Mbean。

还有一件事。 显然,我们必须使用自定义子类而不是org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean 另外,为了收集实际的统计信息,而不是一直看到零,我们必须设置hibernate.generate_statistics标志。

@Bean
def entityManagerFactoryBean() = {
 val entityManagerFactoryBean = new JmxLocalContainerEntityManagerFactoryBean()
 entityManagerFactoryBean.setDataSource(dataSource())
 entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter())
 entityManagerFactoryBean.setPackagesToScan("com.blogspot.nurkiewicz")
 entityManagerFactoryBean.setJpaPropertyMap(
  Map(
   "hibernate.hbm2ddl.auto" -> "create",
   "hibernate.format_sql" -> "true",
   "hibernate.ejb.naming_strategy" -> classOf[ImprovedNamingStrategy].getName,
   "hibernate.generate_statistics" -> true.toString
  ).asJava
 )
 entityManagerFactoryBean
}

这是我们希望在JvisualVM中看到的示例(不要忘记安装所有插件!):

在Hibernate,EhCache,Quartz,DBCP和Spring中启用JMX

另外,我们获得了一个不错的Hibernate日志记录:

HQL: select generatedAlias0 from Book as generatedAlias0, time: 10ms, rows: 20

高速缓存

监视缓存非常重要,尤其是在您希望在那里通常存在值的应用程序中。 我倾向于根据需要频繁查询数据库,以避免不必要的方法参数或本地缓存 一切使代码尽可能简单。 但是,这种方法仅在数据库层上的缓存正常工作时才有效。 与Hibernate相似,在EhCache中启用JMX监视是一个两步过程。 首先,您需要在MBeanServer公开提供的MBean

@Bean(initMethod = "init", destroyMethod = "dispose")
def managementService = new ManagementService(ehCacheManager(), platformMBeanServer(), true, true, true, true, true)

@Bean def platformMBeanServer() = ManagementFactory.getPlatformMBeanServer

def ehCacheManager() = ehCacheManagerFactoryBean.getObject

@Bean def ehCacheManagerFactoryBean = {
 val ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean
 ehCacheManagerFactoryBean.setShared(true)
 ehCacheManagerFactoryBean.setCacheManagerName("spring-pitfalls")
 ehCacheManagerFactoryBean
}

请注意,我明确设置了CacheManager名称。 这不是必需的,但是此名称用作Mbean名称的一部分,并且默认名称包含hashCode值,这不是很好。 最后一点是启用基于缓存的统计信息:

<cache name="org.hibernate.cache.StandardQueryCache"
    maxElementsInMemory="10000"
    eternal="false"
    timeToIdleSeconds="3600"
    timeToLiveSeconds="600"
    overflowToDisk="false"
    memoryStoreEvictionPolicy="LRU"
    statistics="true"
/>

现在,我们可以愉快地分别监视每个缓存的各种缓存特征:

在Hibernate,EhCache,Quartz,DBCP和Spring中启用JMX

如我们所见,缓存未命中的百分比增加了。 从来没有一件好事。 如果我们不启用缓存统计信息,那么启用JMX仍然是一个好主意,因为我们免费获得了许多管理操作,包括刷新和清除缓存(在调试和测试过程中很有用)。

石英调度器

以我的拙见, Quartz Scheduler是一个被低估的库,但是我将自己撰写一篇有关它的文章。 这次,我们将仅学习如何通过JMX对其进行监视。 幸运的是,它就像添加一样简单:

org.quartz.scheduler.jmx.export=true

quartz.properties文件。 Quartz中对JMX的支持可能会稍微扩大一点,但是仍然可以查询例如当前正在运行的作业。 顺便说一下,新的主要版本的Quartz(2.x)带来了非常好的DSL类似的调度支持:

val job = newJob(classOf[MyJob])
val trigger = newTrigger().
  withSchedule(
   repeatSecondlyForever()
  ).
  startAt(
   futureDate(30, SECOND)
  )
scheduler.scheduleJob(job.build(), trigger.build())

Apache Commons DBCP

Apache Commons DBCP是我遇到的最合理的JDBC池库。 还有c3p0 ,但似乎不再积极开发了。 Tomcat JDBC连接池看起来很有前途,但是由于它捆绑在Tomcat中,因此您的JDBC驱动程序不能再打包在WAR中。

DBCP的唯一问题是它不支持JMX。 完全没有(请参见此两年半的旧版 )。 幸运的是,这很容易解决。 此外,我们还将学习如何使用Spring内置的JMX支持。

看起来标准的BasicDataSource拥有我们所需的全部,我们要做的就是通过JMX公开现有的指标。 使用Spring时,它简直就是简单–只需@ManagedAttribute子类,然后在所需的属性上添加@ManagedAttribute批注:

@ManagedResource
class ManagedBasicDataSource extends BasicDataSource {

    @ManagedAttribute override def getNumActive = super.getNumActive
    @ManagedAttribute override def getNumIdle = super.getNumIdle
    @ManagedAttribute def getNumOpen = getNumActive + getNumIdle
    @ManagedAttribute override def getMaxActive: Int= super.getMaxActive
    @ManagedAttribute override def setMaxActive(maxActive: Int) {
        super.setMaxActive(maxActive)
    }

    @ManagedAttribute override def getMaxIdle = super.getMaxIdle
    @ManagedAttribute override def setMaxIdle(maxIdle: Int) {
        super.setMaxIdle(maxIdle)
    }

    @ManagedAttribute override def getMinIdle = super.getMinIdle
    @ManagedAttribute override def setMinIdle(minIdle: Int) {
        super.setMinIdle(minIdle)
    }

    @ManagedAttribute override def getMaxWait = super.getMaxWait
    @ManagedAttribute override def setMaxWait(maxWait: Long) {
        super.setMaxWait(maxWait)
    }

    @ManagedAttribute override def getUrl = super.getUrl
    @ManagedAttribute override def getUsername = super.getUsername
}

以下是一些在负载测试期间疯狂的数据源指标:

在Hibernate,EhCache,Quartz,DBCP和Spring中启用JMX

Spring框架本身对JMX的支持非常简单。 如您所见,公开任意属性或操作只是添加注释的问题。 您只需要记住有关使用XML或Java启用JMX支持的方法(另请参见: SPR-8943:等效于<context:mbean-export />的@Configuration ):

<context:mbean-export/>

要么:

@Bean def annotationMBeanExporter() = new AnnotationMBeanExporter()

这篇文章并不特别令人兴奋。 但是,对JMX指标的了解将使我们能够立即编写简单而精致的仪表板。 敬请关注!

参考: Java和社区博客上的JCG合作伙伴 Tomasz Nurkiewicz提供了在Hibernate,EhCache,Quartz,DBPC和Spring中启用JMX的信息

相关文章 :

翻译自: https://www.javacodegeeks.com/2012/01/enabling-jmx-in-hibernate-ehcache-qurtz.html