0

项目:

我使用 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.

4

1 回答 1

0

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

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

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

于 2014-09-17T21:35:19.410 回答