很多时候, 当后端服务出现性能问题, 如何调优是个难题, 因为当业务变得很复杂, 定位问题十分困难.
企业开发中常用的spring构架提供了一个很好的机制 AOP, 方便我们快速定位问题.
这里演示一个组件, 利用AOP, 打印出 spring 调用栈耗时.
@Component("performanceInspector")
public class PerformanceInspector {
private static class InvokeInfo {
List<MutableTriple<Integer, MethodSignature, Long>> infos = new ArrayList<>();
int currentLevel;
}
private static final ThreadLocal<InvokeInfo> invokeInfoThreadLocal = new InheritableThreadLocal<>();
public Object inspect(final ProceedingJoinPoint pjp) throws Throwable {
MethodSignature signature = (MethodSignature) pjp.getSignature();
InvokeInfo invokeInfo = invokeInfoThreadLocal.get();
boolean isRoot = false;
if (invokeInfo == null) {
invokeInfo = new InvokeInfo();
invokeInfoThreadLocal.set(invokeInfo);
isRoot = true;
}
MutableTriple<Integer, MethodSignature, Long> currInvokeInfo =
MutableTriple.of(invokeInfo.currentLevel++, signature, 0L);
invokeInfo.infos.add(currInvokeInfo);
try {
Tick tick = Tick.tick();
Object result = pjp.proceed();
currInvokeInfo.setRight(tick.nip());
return result;
} finally {
invokeInfo.currentLevel--;
if (isRoot) {
for (MutableTriple<Integer, MethodSignature, Long> info : invokeInfo.infos) {
System.out.println(genInfoStr(info));
}
invokeInfoThreadLocal.set(null);
}
}
}
private String genInfoStr(MutableTriple<Integer, MethodSignature, Long> info) {
return Strings.repeat("\t", info.getLeft())
+ info.getMiddle().getDeclaringType().getSimpleName() + "." + info.getMiddle().getName()
+ " :" + info.getRight() + "ms";
}
}
配置一下AOP:
<aop:config> <aop:aspect ref="performanceInspector" > <aop:around method="inspect" pointcut="execution(* *(..))"/> </aop:aspect> </aop:config>
测试用例
@Component("PerformanceInspectorTest")
public class PerformanceInspectorTest {
@Resource(name = "PerformanceInspectorTest")
PerformanceInspectorTest self;
@Test
public void test() {
self.f();
}
public void f() {
self.a();
self.b();
self.c();
}
public void a() {
self.b();
}
public void b() {
self.c();
}
public void c() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
输出结果
PerformanceInspectorTest.f :306ms
PerformanceInspectorTest.a :99ms
PerformanceInspectorTest.b :99ms
PerformanceInspectorTest.c :99ms
PerformanceInspectorTest.b :99ms
PerformanceInspectorTest.c :99ms
PerformanceInspectorTest.c :99ms