检查并分析AEM实例中是否存在JCR会话泄露

检查并确定AEM 6.x应用程序JCR会话泄露的原因。

描述 description

检查您的AEM 6.x应用程序是否存在JCR会话泄露并跟踪源。

环境

AEM 6.4,6.5

分辨率 resolution

I.检查是否存在会话泄露

  1. 转到  http://host:port/system/console/jmx  并以管理员身份登录。
  2. 使用浏览器的搜索功能查找页面上出现的所有SessionStatistics对象。
  3. 如果找到的对象超过500个,则存在会话泄露。

二、识别泄露会话的代码

如果发现会话泄露,请按照以下步骤查找导致会话泄露的原因。

  1. 向下滚动该页至SessionStatistics对象。
  2. 在新的浏览器选项卡中打开一些SessionStatistics对象,方法是  [Ctrl] +单击部分  列出了时间戳或更高的ID编号。  例如,下面的ID为
  3. 12105:org.apache.jackrabbit.oak "SessionStatistics" "admin@session-12105@Aug 10, 2020 7:03:25 PM" {id=287}
  4. ID编号越高,上次重新启动AEM后创建的会话就越新。
  5. 查看栈栈跟踪,以显示打开了这些会话的代码。
  6. 在栈栈中搜索应用程序java包。  如果代码是应用程序的一部分,请参阅下一部分。

三、修复会话泄露

要防止和修复JCR会话泄露,请执行以下操作:

  • 如果您打开  javax.jcr.Session  然后始终通过以下方式将其关闭  Session.logout()
  • 如果您打开  org.apache.sling.api.resource.ResourceResolver  然后始终通过以下方式将其关闭  ResourceResolver.close()

关闭会话对象:

下面的代码使会话保持打开状态:

try {
Session session = repository.loginAdministrative(null);
Node node = session.getNode("/content/we-retail");
  log.info("Node: " + node.getPath());
} catch (RepositoryException re) {
log.error(re.getMessage(), re);
}

*注意:*除了关闭会话之外,此代码还会调用repository.loginAdministrative来打开会话。 出于安全原因,AEM的更高版本已弃用这种打开会话的方式。

要关闭会话,您可以使用try/finally代码块封装代码并调用session.logout():

Session session = null;
try {
session = repository.loginAdministrative(null);
// use session
} catch (RepositoryException re) {
log.error(re.getMessage(), re);
} finally {
if (session != null && session.isLive()) {
session.logout();
}
}

创建会话或共享会话时要小心。  跨对象共享会话时,将更难跟踪会话打开的位置以及必须关闭会话的时间。  此外,绝不能跨Java Threads共享会话。

关闭ResourceResolver对象:

下面的代码会让ResourceResolver处于打开状态:

try{
ResourceResolver resourceResolver = resourceFactory.getServiceResourceResolver(paramMap);
  Resource resource = resourceResolver.getResource("/content/we-retail");
  log.info("Resource: " + res.getPath());
} catch(Exception e){
log.error(e.getMessage());
}

要关闭resourceResolver,请使用try/finally代码块封装代码并调用resourceResolver.close():

try{
ResourceResolver resourceResolver = resourceFactory.getServiceResourceResolver(paramMap);
  // use ResourceResolver
} catch (Exception e) {
log.error(e.getMessage());
} finally {
if(resourceResolver != null && resourceResolver.isLive()) {
resourceResolver.close();
  }
}

重要说明

通过SlingRequest或WorkflowSession获取的会话和ResourceResolver对象,不应由应用程序关闭。  例如:

slingRequest.getResourceResolver().adaptTo(Session.class);
//Or
workflowSession.getSession();

该解析程序和会话将在处理完请求后自动关闭。

recommendation-more-help
3d58f420-19b5-47a0-a122-5c9dab55ec7f