gpt4 book ai didi

java - 使用 JMX 以编程方式公开调用统计信息

转载 作者:行者123 更新时间:2023-11-28 22:12:37 26 4
gpt4 key购买 nike

我想做的是:通过 JMX 公开调用统计信息(主要是调用计数和平均调用时间)。问题是我想在 AspectJ 支持下执行此操作(为我的实现类自动计算它)。

我创建的是 JmxBean:

public class JmxStatistics implements Serializable {

private final String name;
private long errorCount;
private long errorCallTime;
private long successCount;
private long successCallTime;

public JmxStatistics(String name) {
this.name = name;
}

public synchronized long getCallCount() {
return errorCount + successCount;
}

public synchronized long getAvgCallTimeInMillisecs() {
return (errorCallTime + successCallTime) / getCallCount();
}

public synchronized long getAvgSuccessfulCallTimeInMillisecs() {
return (errorCallTime + successCallTime) / successCount;
}

public synchronized long getAvgFailedCallTimeInMillisecs() {
return (errorCallTime + successCallTime) / errorCount;
}

public synchronized void increaseErrorCallTime(long sumCallTime) {
this.errorCallTime += sumCallTime;
}

public synchronized void increaseSuccessCallTime(long sumCallTime) {
this.successCallTime += sumCallTime;
}

public synchronized long getErrorCount() {
return errorCount;
}

public synchronized void incrementErrorCount() {
this.errorCount++;
}

public synchronized long getSuccessCount() {
return successCount;
}

public synchronized void incrementSuccessCount() {
this.successCount++;
}

@Override
public String toString() {
return name + "{" + "callCount=" + getCallCount()
+ " (s: " + successCount + ",e:" + errorCount + "); "
+ "avgCallTime=" + getAvgCallTimeInMillisecs() + "ms "
+ "(" + getAvgSuccessfulCallTimeInMillisecs() + "ms;e:" + getAvgFailedCallTimeInMillisecs() + "ms)" + "}";
}

AOP 包装点:

public Object wrap(ProceedingJoinPoint joinPoint) throws Throwable {
JmxStatistics jmxs = store.getStatisticsBean(joinPoint);
long start = System.currentTimeMillis();
Object result;
try {
result = joinPoint.proceed();
} catch (Throwable t) {
long runtime = System.currentTimeMillis() - start;
jmxs.incrementErrorCount();
jmxs.increaseErrorCallTime(runtime);
throw t;
}
long runtime = System.currentTimeMillis() - start;
jmxs.incrementSuccessCount();
jmxs.increaseSuccessCallTime(runtime);
return result;
}

还有一个用于公开所有(以编程方式创建的)JMX bean 的存储:

public class JmxStatisticsStore {

private final HashMap<String, JmxStatistics> jmxBeans = new HashMap<>();

public HashMap<String, JmxStatistics> getJmxBeans() {
return jmxBeans;
}

JmxStatistics getStatisticsBean(ProceedingJoinPoint joinPoint) {
String id = joinPoint.getTarget().getClass().toString() + "." + joinPoint.getSignature().getName();
if (!jmxBeans.containsKey(id)) {
synchronized (jmxBeans) {
if (!jmxBeans.containsKey(id)) {
JmxStatistics jmxStatistics = new JmxStatistics(id);
jmxBeans.put(id, jmxStatistics);
}
}
}
return jmxBeans.get(id);
}
}

我想为此使用 Spring AOP 和 MBeanExporter。我的配置如下:

<bean id="jmxStatisticsStore" class="package.JmxStatisticsStore"/>
<bean id="jmxAspect" class="package.AspectJJmxCalculator" />
<aop:config>
<aop:aspect id="jmxAspectId" ref="jmxAspect">

<aop:pointcut id="pointCutAround"
expression="execution(* jmx.tester..*.*(..))" />

<aop:around method="wrap" pointcut-ref="pointCutAround" />
</aop:aspect>
</aop:config>
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
<property name="beans">
<map>
<entry key="bean:name=callStatistics" value-ref="jmxStatisticsStore"/>
</map>
</property>
</bean>

目前,我尝试在 tomcat 中运行它(jmx.tester 包有一个我在 webapp 中使用的 Spring bean)。 Web 应用程序运行正常,使用 JConsole 我可以连接到服务器。在服务器上的 beans 下,我可以看到带有 HashMap 属性的 callStatistics bean。

在我不打电话之前,散列图是空的(这很好)(在“值”框中显示 {})在我调用之后(因此 hashmap 不再为空),值变为不可用,如果我尝试通过 JMX 调用 getJmxBeans 方法,我会得到以下异常:

Problem invoking getJmxBeans: java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
java.lang.ClassNotFoundException: package.JmxStatistics (no security manager: RMI class loader disabled)

编辑:我希望看到的是对不同 ID 的调用显示为单独的 JMX 属性。

有什么办法可以完成我想完成的事情吗?谢谢

最佳答案

设法解决这个问题。修改了 JmxStatisticsStore:

@Autowired
MBeanExporter exporter;

private static final Logger LOG = LogManager.getLogger();
private final HashMap<String, Object> jmxBeans = new HashMap();

JmxData getStatisticsBean(ProceedingJoinPoint joinPoint) {
String id = "bean:name=" + joinPoint.getTarget().getClass().toString() + "." + joinPoint.getSignature().getName();
if (!jmxBeans.containsKey(id)) {
synchronized (jmxBeans) {
if (!jmxBeans.containsKey(id)) {
JmxData jmxStatistics = new JmxData(id);
jmxBeans.put(id, jmxStatistics);
try {
exporter.registerManagedResource(jmxStatistics, new ObjectName(id));
} catch (MalformedObjectNameException ex) {
LOG.warn("Error while registering " + id, ex);
}
}
}
}
return (JmxData) jmxBeans.get(id);
}

这样可以在运行时创建新的 MBean

关于java - 使用 JMX 以编程方式公开调用统计信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26121524/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com