Включение статистики ehcache в jboss 4.2.1
-
05-07-2019 - |
Вопрос
Я установил hibernate.generate_statistics=true, и теперь мне нужно зарегистрировать mbeans, чтобы я мог видеть статистику в консоли jmx.Кажется, я ничего не могу добиться, и это не должно быть такой уж сложной проблемой.Возможно, я все усложняю, но в любом случае до сих пор я пробовал:
- Я скопировал EhCacheProvider и создал экземпляр расширенной версии CacheManager, которая перегрузила init() и вызвала ManagementService.registerMBeans(...) после инициализации.Весь код работал нормально до тех пор, пока фактический вызов RegisterMBeans(...) не привел к сбою инициализации провайдера с общей ошибкой (к сожалению, я не записал ее). Этот подход был мотивирован методами, использованными в это пошаговое руководство по производительности liferay.
- Я создал свой собственный MBean с методом запуска, который запускал код, аналогичный этот пример регистрации jmx mbeans ehcache.Кажется, все работает правильно, и мой mbean отображается в консоли jmx, но ничего для net.sf.ehcache.
- С тех пор я обновил ehcache до 1.5 (мы использовали 1.3, не уверен, относится ли это к jboss 4.2.1 или просто что-то, что мы выбрали сами) и перешел на использование SingletonEhCacheProvider и пытаюсь просто вручную получить статистику вместо того, чтобы иметь дело с регистрация mbean.Однако на самом деле дела пошли не лучше;если я вызываю getInstance(), возвращаемый CacheManager содержит только копию StandardQueryCache, но журналы jboss показывают, что было инициализировано множество других кешей (по одному для каждого из кэшированных объектов в нашем приложении).
РЕДАКТИРОВАТЬ:Ну, я понял одну вещь... подключение через JConsole действительно показывает статистику mbeans.Я предполагаю, что ManagementFactory.getPlatformMBeanServer() не предоставляет вам тот же сервер mbean, который использует jboss.В любом случае, похоже, я столкнулся с той же проблемой, что и при попытке собрать статистику вручную, потому что я получаю все нули даже после некоторого нажатия на мое приложение.
Решение 2
Решено.Поскольку я не видел всех кэшей своих объектов, я подозревал, что получаю не тот экземпляр 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);
}
Вы также можете использовать этот метод getCacheManager() из UtilMgr, если хотите получить статистику вручную (что я, вероятно, в любом случае сделаю). Вы можете найти дополнительную информацию о том, как использовать объекты Cache и Статистика. в примерах кода ehcache.
Если кто-нибудь может рассказать мне о способе статического поиска фабрики сеансов без необходимости создания этого дополнительного сеансового компонента, я был бы рад это услышать.
Другие советы
В ответе, приведенном выше, предполагается, что используется SingletonEhcacheProvider, и ему также нужен bean-компонент utilmgr, это другое решение использует стартовый 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 будет вторым сервером mbean в таких средах, как Linux.