0

我已经设置了 hibernate.generate_statistics=true 并且现在需要注册 mbean 以便我可以在 jmx 控制台中看到统计信息。我似乎无处可去,这似乎不应该是一个如此困难的问题。也许我让事情变得过于复杂,但无论如何到目前为止我已经尝试过:

  • 我复制了 EhCacheProvider 并让它实例化了 CacheManager 的扩展版本,该版本重载了 init() 并在初始化后调用了 ManagementService.registerMBeans(...) 。在实际调用 registerMBeans(...) 之前,代码都运行良好,这将导致提供程序初始化失败并出现一般错误(不幸的是我没有写下来。)这种方法的动机是this liferay中使用的方法性能演练。
  • 我使用 start 方法创建了自己的 MBean,该方法运行与注册 ehcache 的 jmx mbeans 的示例类似的代码。一切似乎都正常工作,我的 mbean 出现在 jmx 控制台中,但 net.sf.ehcache 没有。
  • 我已经将ehcache升级到1.5(我们使用的是1.3,不确定这是特定于jboss 4.2.1还是我们自己选择的东西)并改为使用SingletonEhCacheProvider并尝试手动获取统计信息而不是处理mbean 注册。但它并没有真正变得更好。如果我调用 getInstance(),则返回的 CacheManager 仅具有 StandardQueryCache 的副本,但 jboss 日志显示许多其他缓存已被初始化(一个用于我们应用程序中的每个缓存实体。)

编辑:嗯,我已经想通了一件事......通过 JConsole 连接确实揭示了统计数据 mbean。我猜 ManagementFactory.getPlatformMBeanServer() 并没有为您提供与 jboss 使用的相同的 mbean 服务器。无论如何,看起来我遇到了与尝试手动收集统计信息时类似的问题,因为即使在单击我的应用程序一段时间后我也得到了全零。

4

2 回答 2

1

上面给出的答案假设正在使用 SingletonEhcacheProvider 并且它还需要 utilmgr bean,这个其他解决方案使用启动 bean 并且不做单例假设

@Name("hibernateStatistics")
@Scope(ScopeType.APPLICATION)
@Startup
public class HibernateUtils {
@In
private EntityManager entityManager;

@Create
public void onStartup() {
    if (entityManager != null) {
        try {
            //lookup the jboss mbean server
            MBeanServer beanServer = org.jboss.mx.util.MBeanServerLocator.locateJBoss();
            StatisticsService mBean = new StatisticsService();
            ObjectName objectName = new ObjectName("Hibernate:type=statistics,application=<application-name>");
            try{
                beanServer.unregisterMBean(objectName);
            }catch(Exception exc) {
                //no problems, as unregister is not important
            }
            SessionFactory sessionFactory = ((HibernateSessionProxy) entityManager.getDelegate()).getSessionFactory();
            mBean.setSessionFactory(sessionFactory);
            beanServer.registerMBean(mBean, objectName);

            if (sessionFactory instanceof SessionFactoryImplementor ){
                CacheProvider cacheProvider = ((SessionFactoryImplementor)sessionFactory).getSettings().getCacheProvider();
                if (cacheProvider instanceof EhCacheProvider)  {
                    try{
                        Field field = EhCacheProvider.class.getDeclaredField("manager");
                        field.setAccessible(true);
                        CacheManager cacheMgr = (CacheManager) field.get(cacheProvider);
                        ManagementService.registerMBeans(cacheMgr, beanServer, true, true, true, true);
                    }catch(Exception exc) {
                        //do nothing
                        exc.printStackTrace();
                    }
                }
            }

        } catch (Exception e) {
            throw new RuntimeException("The persistence context " + entityManager.toString() + "is not properly      configured.", e);
        }
    }
 }

}

我们使用 MbeanServerLocator,因为 jboss mbean 将是 linux 等环境中的第二个 mbean 服务器。

于 2010-04-07T09:34:38.790 回答
0

解决了。由于我没有看到我的实体的所有缓存,我怀疑我没有获得正确的 SessionFactory 实例。我从这一行开始(请参阅我在问题中提供的链接中的示例 jmx 注册代码):

SessionFactory sf = (new Configuration()).configure().buildSessionFactory();

最终结果是我最终得到的缓存管理器是一个新实例,而不是持久性上下文中的那个。所以我尝试重构为:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("myPersistenceUnit");
return ((EntityManagerFactoryImpl)emf).getSessionFactory();

但这只是抛出了一个异常(我不记得确切的文本;“无法初始化持久性上下文”的效果。)所以没有其他选项,我在我的应用程序中添加了一个无状态 bean (UtilMgr) 并让持久性注入正确的 SessionFactory。这是那个豆子:

import javax.ejb.Stateless;
import javax.persistence.PersistenceUnit;
import net.sf.ehcache.CacheManager;
import org.hibernate.SessionFactory;

@Stateless
public class UtilMgrBean implements UtilMgr {
    // NOTE: rename as necessary
    @PersistenceUnit(unitName = "myPersistenceCtx")
    private SessionFactory sessionFactory;

    public SessionFactory getSessionFactory() {
        return this.sessionFactory;
    }

    public CacheManager getCacheManager() {
        return CacheManager.getInstance(); // NOTE: assumes SingletonEhCacheProvider
    }
}

这是前面提到的演练中的更正代码:

try {
    // NOTE: lookupBean is a utility method in our app we use for jndi lookups.
    //   replace as necessary for your application.
    UtilMgr utilMgr = (UtilMgr)Manager.lookupBean("UtilMgrBean", UtilMgr.class);
    SessionFactory sf = utilMgr.getSessionFactory();
    MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

    // NOTE: replace myAppName as necessary
    ObjectName on = new ObjectName("Hibernate:type=statistics,application=myAppName");

    // Enable Hibernate JMX Statistics
    StatisticsService statsMBean = new StatisticsService();
    statsMBean.setSessionFactory(sf);
    statsMBean.setStatisticsEnabled(true);
    mbs.registerMBean(statsMBean, on);

    CacheManager cacheMgr = utilMgr.getCacheManager();
    ManagementService.registerMBeans(cacheMgr, mbs, true, true, true, true);
} catch(Throwable t) {
    throw new RuntimeException(t);
}

如果您想手动检索统计信息,您也可以使用 UtilMgr 的 getCacheManager() 方法(无论如何我可能都会这样做。)您可以在 ehcache 代码示例中找到有关如何使用缓存和统计对象的更多信息。

如果有人可以告诉我静态查找会话工厂而不需要创建这个额外的会话 bean 的方法,我很想听听。

于 2008-10-30T21:19:34.140 回答