簡體   English   中英

在Tomcat中通過帶有Spring的JMX公開Hibernate(緩存)統計信息

[英]Exposing Hibernate (cache) statistics through JMX with Spring in Tomcat

在基於Spring的設置中收集Hibernate / Ehcache統計信息並通過JMX公開它們似乎很容易。 互聯網上有很多資源可以提供幫助,例如http://snippets.dzone.com/posts/show/11159

但是,所有這些文章都假設有人正在使用某種Hibernate會話工廠。 我不是-我的實體帶有JPA批注,並且使用javax.persistence.EntityManager 如果我要部署到Java EE容器,則可以通過JNDI獲得Hibernate會話工廠,如此處所述http://internna.blogspot.com/2007/08/hibernate-statistics-in-enterprise-5.html但我在使用Tomcat ...

怎么去這個? 我還沒有想出解決方案。

如果我引用了Ehcache CacheManager ,則可以嘗試以下操作:

<context:mbean-server />
<bean class="net.sf.ehcache.management.ManagementService" init-method="init">
  <constructor-arg ref="..myCacheManager.."/>
  <constructor-arg ref="mbeanServer"/>
  <constructor-arg value="true"/>
  <constructor-arg value="true"/>
  <constructor-arg value="true"/>
  <constructor-arg value="true"/>
</bean>

由於緩存管理器是由Hibernate創建的(即它不是Spring Bean),因此將無法工作。 我嘗試用

<constructor-arg><bean id="cacheManager" class="net.sf.ehcache.CacheManager" factory-method="getInstance"/></constructor-arg>

希望我能以某種方式抓住合適的實例。 也不起作用,因為這實際上會創建一個新的緩存管理器實例。

我最近構建了一個基於Spring的示例Web應用程序,該應用程序非常干凈地為JMX啟用了Spring,Hibernate和Ehcache的最新版本。

它具有基於EntityManager和DAO訪問(包括事務!)的示例。 它還顯示了如何進行基於注解的注入,以便不必為豆使用Spring的xml配置。 甚至還有一個使用注釋的基於SpringMVC的示例servlet。 基本上,這是運行在任何servlet引擎之上的功能強大的應用程序服務器的基於Spring的版本。

它尚未記錄,但我會盡快解決。 看一下配置文件和源代碼,它應該很清楚。

其背后的動機是,我厭倦了用50種不同方式進行設置的所有瘋狂博客文章,並最終使人們可以使用一個簡單的來源。 它位於github上,因此可以隨意分叉該項目並對其進行任何操作。

https://github.com/lookfirst/fallback

實際上,您可以使用Spring Expression Language公開任何CacheManager。

<bean id="hibernateCacheManagement" class="net.sf.ehcache.management.ManagementService" init-method="init" >
    <constructor-arg value="#{T(net.sf.ehcache.CacheManager).getCacheManager('CACHE_NAME')}"/>
    <constructor-arg><ref bean="mbeanServer"/></constructor-arg>
    <constructor-arg value="true"/>
    <constructor-arg value="true"/>
    <constructor-arg value="true"/>
    <constructor-arg value="true"/>
</bean>

其中CACHE_NAME是在ehcache.xml文件中配置的緩存的名稱。

<ehcache name="CACHE_NAME">
    ...
</ehcache>

JPA EntityManager公開了基礎的Hibernate會話,因此您可以使用其Factory:

   public static Session getHibernateSession(EntityManager entityManager) {
        Session session;
        if (entityManager.getDelegate() instanceof EntityManagerImpl) {
            EntityManagerImpl entityManagerImpl = (EntityManagerImpl) entityManager.getDelegate();
            session = entityManagerImpl.getSession();
        } else {
            session = (Session) entityManager.getDelegate();
        }

        return session;
    }

然后,您可以像使用RHQ項目一樣使用此Session 啟用統計信息

我最終寫了下面的課

HibernateStatisticsJmxRegistration

import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.persistence.EntityManagerFactory;

import org.hibernate.SessionFactory;
import org.hibernate.ejb.HibernateEntityManagerFactory;
import org.hibernate.jmx.StatisticsService;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * Provides code to register Hibernate's statistics bean with a JMX MBean server. Assumes that both
 * the MBeanServer and the EntityManagerFactory are available as Spring-managed beans. Note that
 * while registering this class enables the collection of statistics even if that was previously
 * disabled.
 * <p>
 * May become obsolete once <a href="https://hibernate.onjira.com/browse/HHH-6034">HHH-6034</a> is
 * implemented. Even if not the confusing situation abround the meanwhile deprecated
 * {@link StatisticsService} should be clear then.
 */
@SuppressWarnings({"deprecation", "javadoc" })
public class HibernateStatisticsJmxRegistration {

  @Autowired
  private EntityManagerFactory entityManagerFactory;

  @Autowired
  private MBeanServer mbeanServer;

  private ObjectName objectName;

  private String jmxObjectName = "org.hibernate:name=HibernateStatistics";

  /**
   * Registers the statistics MBean that wraps a Hibernate session factory. The bean is registered
   * under the name provided by {@link HibernateStatisticsJmxRegistration#getJmxObjectName()}.
   *
   * @throws JMException if anything fails..
   * @see HibernateStatisticsJmxRegistration#unregister()
   */
  public void register() throws JMException {
    final SessionFactory sessionFactory = ((HibernateEntityManagerFactory) entityManagerFactory).getSessionFactory();

    objectName = new ObjectName(jmxObjectName);

    final StatisticsService statsMBean = new StatisticsService();
    statsMBean.setSessionFactory(sessionFactory);
    statsMBean.setStatisticsEnabled(true);
    mbeanServer.registerMBean(statsMBean, objectName);
  }

  /**
   * Unregisters the MBean that was registered.
   *
   * @throws JMException if the de-registration fails
   * @see HibernateStatisticsJmxRegistration#register()
   */
  public void unregister() throws JMException {
    mbeanServer.unregisterMBean(objectName);
  }

  /**
   * Override the default JMX object name. Obviously you need to call this method before
   * registration for it to have any effect. The string must comply to the rules described in
   * {@link ObjectName}. Suggested is {@code <domain>:name=<name>}.
   *
   * @param jmxObjectName the name to use during registration
   */
  public void setJmxObjectName(String jmxObjectName) {
    this.jmxObjectName = jmxObjectName;
  }
}

彈簧配置

<!-- Setting up Ehcache manager for various caches (offer facade, images). -->
<bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
  <property name="configLocation" value="classpath:ehcache.xml" />
</bean>  
<ehcache:annotation-driven cache-manager="ehCacheManager" />

<!-- Exposing cache statistics through JMX. -->
<context:mbean-server />
<bean class="net.sf.ehcache.management.ManagementService" init-method="init">
  <constructor-arg ref="ehCacheManager"/>
  <constructor-arg ref="mbeanServer"/>
  <constructor-arg value="true"/>
  <constructor-arg value="true"/>
  <constructor-arg value="true"/>
  <constructor-arg value="true"/>
</bean>    
<bean class="HibernateStatisticsJmxRegistration"
      init-method="register" destroy-method="unregister" />

非常有幫助,但這也行得通,其中(猜測什么)mbeanServer是MBean Server的bean名稱,而entityManagerFactory是EntityManagerFactory的bean名稱:

<bean id="managementService-ehcache-hibernate"
    class="net.sf.ehcache.management.ManagementService"
    init-method="init"
    destroy-method="dispose">

    <constructor-arg value="#{T(org.springframework.security.util.FieldUtils).getFieldValue(@entityManagerFactory.cache.unwrap(T(org.hibernate.cache.spi.RegionFactory)),'manager')}"/>
    <constructor-arg ref="mbeanServer"/>
    <constructor-arg index="2" value="true"/>
    <constructor-arg index="3" value="true"/>
    <constructor-arg index="4" value="true"/>
    <constructor-arg index="5" value="true"/>
</bean>

Spring僅在JMX上公開他的bean,但是您可以通過MBeanExporter以編程方式導出資源。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM