【问题标题】:JMX-SflowAgent stops collecting JVM metrics from aspectj instrumented WebSphere Application ServerJMX-SflowAgent 停止从 aspectj 检测的 WebSphere Application Server 收集 JVM 指标
【发布时间】:2014-09-11 11:20:56
【问题描述】:

项目:

我使用 Sflow + Ganglia 来监控 Websphere Application Server (WAS) 的 JVM 指标。 WAS 使用 AspectJ 方面进行检测。我添加了一个方面来测量所有应用程序方法的运行时间。

我使用 Hsflowd 作为 JVM 指标收集器。 Hsflowd 在内部使用JMX-SflowAgent javaagent 挂钩到 JVM 以使用 MXBean(RuntimeMXBean、GarbageCollectorMXBean、CompilationMXBean 和 ThreadMXBean)收集指标。

问题:

当我在没有 aspectjweaver 挂钩的情况下运行 WAS 时,我可以连续查看 Ganglia Web 中的所有指标(CPU、桌面、内存、进程等)。但是当将 aspectjweaver 添加到 JVM args 并重新启动服务器后,我可以看到 10 分钟的指标,但之后它不会在 Ganglia web 中报告 JVM 指标。

在 Aspectj 编织日志中,我可以看到 AspectJ 正在编织 JMXsflowAgent 代码。即使它被!call(* com.sflow.JMX.SFlowAgent(..)) 排除在外。

方面:

package com.foo.main;

import java.io.*;
import java.lang.reflect.Method;
import java.security.Signature;
import java.util.*;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.osgi.service.application.ApplicationAdminPermission;

@Aspect
public class ResponseTimeAspect {
    @Pointcut(
        "execution(* com.foo.*(..)) && " +
        "!within(com.foo.main.ResponseTimeAspect) && " + 
        "!within(ThreadLocal+) && " + 
        "!within(&& !within(*..*Aspect)) && " + 
        "!within(com.foo.main.AppInformationReader) && " + 
        "!within(@org.aspectj.lang.annotation.Aspect *) && " + 
        "!within(com.sflow.jmx.SFlowAgent) && " + 
        "!(call( * com.sflow.jmx.SFlowAgent(..)))"
    )
    public void loggingResponseTime() {}

    private static ThreadLocal<String> uuidContainer = new ThreadLocal<String>() {
        @Override
        protected String initialValue(){
            return UUID.randomUUID().toString();
        } 
    };

    AppInformationReader logWriter = AppInformationReader.getInstance();

    @Around("loggingResponseTime()")
    public Object tracing(ProceedingJoinPoint thisJoinPoint) throws Throwable {

        Long startTime= System.currentTimeMillis();
        Long startTotalMemory = Runtime.getRuntime().totalMemory();
        Long startFreeMemory = Runtime.getRuntime().freeMemory();

        Object ret = thisJoinPoint.proceed();

        Long elapsedTime=System.currentTimeMillis() - startTime;
        Long endTotalMemory = Runtime.getRuntime().totalMemory();
        Long endFreeMemory = Runtime.getRuntime().freeMemory(); 
        String methodSignature=thisJoinPoint.getSignature().toString();
        String classname=methodSignature.split("\\.")[thisJoinPoint.getSignature().toString().split("\\.").length-1];
        String methodName =thisJoinPoint.getSignature().getDeclaringType().getCanonicalName();
        logWriter.writeLog(uuidContainer.get().toString(), startTime, System.currentTimeMillis(), elapsedTime, classname, methodName);
        return ret;
     }
}

JMX 包在com.sflow.jmx.SFlowAgent 下。

【问题讨论】:

  • 对于我们看不到的 AspectJ 或 Java 代码以及我们也看不到的配置,很难说任何智能。也许您想考虑提供更多细节,因为这里没有人拥有魔法水晶球。
  • @Kriegaex- 不需要进一步配置.. 我认为 JMX 和 AspectJ 不会在我们的桌面上一起工作。
  • aspectj 正在编织 JMX 代码,尽管它不在执行中(* com.foo..*)切入点.. 我已经为 aspectj 编织启用了调试,并且看到 aspectj 正在编织 run() 方法也属于 JMX 代理。我不确定,但这可能是这里的问题。我的切入点是stackoverflow.com/questions/25663050/…
  • 您是否阅读并理解了我在其他主题中的答案和cmets?!你的切入点拦截了一切,试着把它限制在你感兴趣的范围内。如果你不听答案,就不要问。如果你认为你知道答案,即使它显然是错误的,你为什么在这里?如果您对学习 AspectJ 基础知识不感兴趣,为什么还要冒险使用它?
  • 我完全理解你的回答,甚至接受了你的回答。抱歉没有解释清楚。我已经编辑了我的问题以使其更清楚。

标签: hadoop aspectj jmx ganglia ibm-was


【解决方案1】:

免责声明:这是一个答案,但还不是一个解决方案。写更多评论没有意义,所以我宁愿在这里完善我的答案,因为我会从 Vimlesh 收集更多信息。

好的,仅通过方面而不是真正的 SSCCE 显示问题行为是不可能重现您的问题的。有很多悬而未决的问题:

  • 我不知道方面应用到多少类,
  • 应用服务器中有多少线程和
  • 不再显示 JMX 结果之前和之后 10 分钟的内存消耗情况。
  • 您说 SFlow 代理只运行一次,而不是每 10 秒运行一次。你怎么知道的?您能否提供信息来解释您是如何发现该行为以及如何重现该行为,最好在没有应用服务器但使用普通 Java SE VM 的情况下进行?
  • 我还想知道为什么方面会收集有关空闲内存的信息。这不是其他 Java 代理应该做的吗?为什么要重复两次?
  • 让我感到奇怪的是,名为logWriter 的变量是AppInformationReader 的一个实例。那么它是什么,读者还是作家?班级是做什么的?方面使用它,但未显示。
  • 到底为什么要在方面中为每个线程创建UUIDs,它们的用途是什么?正如我在您之前发布的另一个问题中已经说过的那样,它们似乎没有增加任何价值。你当时没有回答这个问题,现在可以吗?这看起来像是无用的开销。
  • 切入点是多余的。例如
    • execution(* com.foo.*(..)) 仅捕获直接在包com.foo 下的类中的方法执行,但不捕获任何子包中的方法执行。所以从子包中排除类是没有用的。可能你真正想要的是execution(* com.foo..*(..)) - 注意foo..* 中的两个点表示子包。
    • 您误解了我在另一个问题中的回答,因为您没有选择我的解决方案中的一个来排除方面及其内部使用的匿名ThreadLocal 子类,而是串联所有 em> 其中有&amp;&amp;。这并没有使它变得更好或更易读。
    • 您尝试排除call( * com.sflow.jmx.SFlowAgent(..)),但有两个原因没有必要:首先,SFlowAgent 不在目标包com.foo 中。其次,execution() 连接点不能同时是call() 连接点,因此交集必须为空 - 无需从执行中排除调用。
    • 此语法无效:!within(&amp;&amp; !within(*..*Aspect)) - 可能是与嵌套的 within() 子句有关的复制和粘贴错误。

话虽如此,你可能想要这个切入点:

execution(* com.foo..*(..)) &&
!within(@org.aspectj.lang.annotation.Aspect *) &&
!within(com.foo.main.AppInformationReader)

应该够了。

修复切入点后,您可以尝试停止收集和记录切面中的信息,以提高效率。至于其他 Java 代理,无需将其从切面编织中排除,但可能需要将切面排除在 SFlowAgent 的目标之外。也许 SFlow 代理检测的方面代码存在问题,但这只是猜测。也许你的配置是错误的,也许是别的。在我看来,您好像在尝试使用两种您从未学会使用得很好的武器(工具)。如果没有 SSCCE,真的很难诊断问题的根本原因。

更新:您还可以尝试将 AspectJ weaver 列为 JVM 命令行上的第一个 Java 代理,即在 SFlow 代理之前。测试它是否有任何不同。

【讨论】:

  • 非常感谢 kriegaex 指出我切入点中的错误。我一定会学习并纠正它。我已经在我的工作副本中进行了更改,但是由于代码很大并且在复制粘贴时发生了一些错误。使用 -loadersToSkip 选项解决了问题,我避免为加载 Sflowagent 类的加载程序编织。现在它工作正常。非常感谢您的帮助。请更新答案
  • 我应该在我的答案中编辑什么?你没有回答我的任何问题或听从我的建议。相反,您告诉我您找到了一种解决方法,这很好。但根本原因一定是不同的,因为您在此处显示的切入点不应该编织另一个代理。也许你有另一个这样做,我不知道。请分享一个 SSCCE,以便我们都可以重现原始问题并学习一些东西。我最近花了很多时间试图帮助你,但你似乎忽略了我的大部分提示,从不分享完整的信息,也无助于使问题重现。
  • 让我试着回答你的问题 - 它应该在 com.foo..* 包下编织所有类。由于这方面是针对 APM 工具的,而且我们对代码一无所知,因此应用服务器中没有线程。目的是编织 com.foo..* 包下的所有类,并获取为 1 个调用流执行的所有方法的响应时间。不再显示 JMX 结果之前和之后的 10 分钟内没有内存消耗。我已经从代码中添加的调试中下载了代码,并使用此自定义代码执行。我可以看到 ru() 下的调试只被调用了一次。
  • 如何重现 - 将 Aspectjweaver 和 sflowagent.jar 与任何应用程序服务器一起运行。 AppInformationReader 最初仅用于读取一些用户定义的数据,后来我使用相同的类将数据(UUID、responseTime、methodName 和 className)转储到日志文件。一旦我能够解决我的功能问题,我将根据单一责任原则进行更正。 UUID 用于分布式事务的唯一标识。我们有分布式事务,因此我需要为单个分布式事务收集所有 Hops 的数据。
  • sflowagent jmx-sflow-agent.googlecode.com/svn/trunk/src/com/sflow/jmx/… 有一些 MXBEANS 在编织后被损坏。正在损坏的代码是 /* OperatingSystemMXBean osMX = ManagementFactory.getOperatingSystemMXBean(); String className = osMX.getClass().getName(); if("com.sun.management.OperatingSystem".equals(className) || "com.sun.management.UnixOperatingSystem".equals(className)) { */.我还是不知道这段代码出了什么问题。跨度>
猜你喜欢
  • 1970-01-01
  • 2014-10-22
  • 1970-01-01
  • 2023-03-15
  • 2016-10-01
  • 2018-08-22
  • 2017-12-24
  • 2023-01-31
  • 1970-01-01
相关资源
最近更新 更多