项目:
我使用sflow+ganglia来监视websphereapplicationserver(was)的jvm度量。was使用aspectj方面进行检测。我添加了一个方面来度量所有应用程序方法运行时。
我使用hsflowd作为jvm度量收集器。hsflowd在内部使用jmxsflowagent javaagent钩住jvm,使用mxbean(runtimemxbean、garbagecollectormxbean、compilationmxbean和threadmxbean)收集度量。
问题:
当我在没有aspectjweaverhook的情况下运行was时,我可以连续地看到gangliaweb中的所有指标(cpu、桌面、内存、进程等)。但是当aspectjweaver被添加到jvm参数中并且在重启服务器之后,我可以看到10分钟的指标,但是在那之后它不会在gangliaweb中报告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
.
1条答案
按热度按时间wfsdck301#
免责声明:这是一个答案,但还不是一个解决方案。写更多的评论是没有意义的,所以我宁愿在这里完善我的答案,因为我从 vim 勒那里收集了更多的信息。
好吧,仅仅用一个方面而不是一个真正的sscce来显示问题行为是不可能重现你的问题的。有很多悬而未决的问题:
我不知道这方面应用到多少类,
应用程序服务器和服务器中有多少线程
jmx结果不再显示之前10分钟和之后10分钟的内存消耗情况。
你说sflow代理只运行一次,而不是每10秒运行一次。你怎么知道的?您能否提供一些信息来解释您是如何发现的,以及如何在没有应用服务器但使用普通javasevm的情况下最佳地再现这种行为?
我还想知道为什么方面收集有关空闲内存的信息。这不是另一个java代理应该做的吗?为什么要做两次?
我觉得奇怪的是
logWriter
是的示例AppInformationReader
. 那它是什么,读者还是作家?这个班是做什么的?方面使用它,但它没有显示。你究竟为什么要创造
UUID
在方面中,每个线程使用的是什么?它们似乎没有增加任何价值,正如我在你先前发布的另一个问题中所说的那样。你当时没有回答这个问题,现在能回答吗?头顶看起来没用。切入点太过分了。例如
execution(* com.foo.*(..))
只捕获直接在包下的类中的方法执行com.foo
,但不在任何子包中。因此,从子包中排除类是无用的。也许你真正想要的是execution(* com.foo..*(..))
-注意下面的两点foo..*
表示子包。您误解了我在另一个问题中的回答,因为您没有选择我的解决方案之一来排除方面及其内部使用的匿名
ThreadLocal
子类,但用&&
. 这并不能使它更好或更可读。你试图排除
call( * com.sflow.jmx.SFlowAgent(..))
但有两个原因:第一,SFlowAgent
不在目标包中com.foo
. 其次,一个execution()
joinpoint永远不能是call()
同时连接点,因此交叉集必须为空-无需从执行中排除调用。此语法无效:
!within(&& !within(*..*Aspect))
-可能是有关嵌套对象的复制和粘贴错误within()
条款。话虽如此,你可能想要这个切入点:
这应该够了。
在修复了切入点之后,您可以尝试停止收集和记录方面的信息,以提高效率。至于另一个java代理,不需要将其排除在方面编织之外,但是可能需要将方面排除在对象的目标之外
SFlowAgent
. 也许sflow代理检测方面代码时有问题,但这只是猜测。也许你的配置不对,也许是别的什么。在我看来,你似乎在试图挥舞两种你从未学好的武器(工具)。没有sscce,很难诊断问题的根本原因。更新:您还可以尝试将aspectjweaver列为jvm命令行上的第一个java代理,即在sflow代理之前。测试是否有任何区别。