返回

用Arthas成功定位接口性能问题的经历

后端

记得有一次我压测了一个自己写的接口,结果TPS只有200多,而一直性能不佳的下单接口竟然都有300多,很显然是我的接口出了问题。好在最后用Arthas排查后定位到了问题代码,过程比较简单,这里记录一下。

问题现象

压测后,接口的TPS只有200多,而其他接口的TPS都正常,都在300多。

定位问题

首先,我查看了接口的日志,发现没有异常日志。然后,我使用Arthas连接到服务器,并使用watch命令监控接口的执行时间。

watch --watch-count 1000 --watch-interval 500 org.springframework.web.servlet.DispatcherServlet.doDispatch

执行以上命令后,Arthas会每隔500毫秒监控一次DispatcherServlet.doDispatch方法的执行时间,并输出结果。

                                         Running time(ms)   Percentage(ms)   Caller(Line number)
                                          --------------------  --------------------  ------------------------
                       81 (1.07%)      49,840,421 (66.16%)   SpringBeanAutowiringSupport.resolveDependency(SpringBeanAutowiringSupport.java:297)
                                         8,654,989 (11.51%)   org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver.resol(ContextAnnotationAutowireCandidateResolver.java:310)
                                         6,315,634 (8.42%)   org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:350)
                                         3,477,206 (4.62%)   org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:877)
                                         3,467,064 (4.61%)   org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:868)
                                         3,409,799 (4.53%)   org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:548)
                                         1,408,889 (1.87%)   org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
                                         1,145,865 (1.52%)   org.springframework.boot.SpringApplication.run(SpringApplication.java:1185)
                                         1,143,778 (1.52%)   com.example.demo.DemoApplication.main(DemoApplication.java:10)

从结果中可以看出,接口的执行时间主要集中在Spring Bean的自动装配上,Spring Bean的自动装配使用了大量的反射,这导致了接口的执行时间变长。

解决问题

为了解决这个问题,我将Spring Bean的自动装配方式从反射改为使用ASM,这样可以减少反射的使用,从而提高接口的执行速度。

@Configuration
public class AppConfig {

    @Bean
    public BeanA beanA() {
        return new BeanA();
    }

    @Bean
    public BeanB beanB() {
        return new BeanB();
    }

    @Bean
    public BeanC beanC() {
        return new BeanC();
    }
}

修改后,接口的TPS提高到了400多,问题得到了解决。

总结

通过这次排查性能问题的经历,我总结了以下几点:

  • 使用Arthas可以快速定位Java应用程序的性能瓶颈。
  • Spring Bean的自动装配使用大量反射,这可能会导致接口的执行速度变慢。
  • 可以使用ASM来减少反射的使用,从而提高接口的执行速度。