zoukankan      html  css  js  c++  java
  • 基于Spring AOP实现对外接口的耗时监控

    AOP是Spring的核心,Spring不但自身对多种框架的集成是基于AOP,并且以非常方便的形式暴露给普通使用者。以前用AOP不多,主要是因为它以横截面的方式插入到主流程中,担心导致主流程代码不够清晰,定位问题不够方便,而在计费二期的项目里需要一个很适合用AOP来做的功能,就是要把对外接口和所调用的外部接口的耗时时间给记录下来,这个需求主要来自于计费一期的联调,常常发生系统间交互不够顺畅的情况,这就需要看每个接口调用时间来判定是谁的问题。

    计费中心是整个后台系统的中间环节,与其他系统交互很多,这样的接口也很多,如果在每个接口的调用前后加时间记录比较繁琐,也影响主流程代码的美观,因此比较优雅的方式是用AOP,在不侵入原有代码的情况下,加上对接口调用的监控,并且可以在不需要的时候很容易移除。今天尝试了一下,感觉还挺好用,下面讲述一下实施步骤:

    1)引入包依赖

    本项目基于maven构建,因此加上包依赖比较方便,我需要的AOP依赖库有以下三个:

    [xhtml] view plaincopy
    1. <dependency>  
    2.   <groupId>org.springframework</groupId>  
    3.   <artifactId>spring-aop</artifactId>  
    4.   <version>2.5.6</version>  
    5. </dependency>  
    6. <dependency>  
    7.   <groupId>org.aspectj</groupId>  
    8.   <artifactId>aspectjweaver</artifactId>  
    9.   <version>1.6.1</version>  
    10. </dependency>  
    11. <dependency>  
    12.   <groupId>org.aspectj</groupId>  
    13.   <artifactId>aspectjrt</artifactId>  
    14.   <version>1.6.1</version>  
    15. </dependency>   

    2)加上AOP的Spring配置文件

    billing-spring-aop.xml:

    [xhtml] view plaincopy
    1. <?xml version="1.0" encoding="UTF-8"?>     
    2. <beans xmlns="http://www.springframework.org/schema/beans"    
    3.  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
    4.  xmlns:aop="http://www.springframework.org/schema/aop"    
    5.  xmlns:tx="http://www.springframework.org/schema/tx"    
    6.  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd    
    7.  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd    
    8.  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">    
    9.    
    10.  <bean id="openApiLogAspect" class="com.alibaba.itbu.billing.framework.aop.OpenApiLogAspect">  
    11.  </bean>    
    12.    
    13.  <aop:config>    
    14.   <!-- 配置aspect切面类 -->    
    15.   <aop:aspect ref="openApiLogAspect">    
    16.    <!-- 配置pointcut,即切入点,对哪些类的哪些方法起到AOP的作用 -->    
    17.    <aop:pointcut id="EsbPriceService"  
    18.     expression="execution(* org.esb.biz.product.EsbPriceService.*(..))" />    
    19.    <aop:pointcut id="EsbProductService"  
    20.     expression="execution(* org.esb.biz.product.EsbProductService.*(..))" />    
    21.    <aop:pointcut id="IAuthorizeControllerService"  
    22.     expression="execution(* com.alibaba.bss.pc2.server.remoting.IAuthorizeControllerService.*(..))" />      
    23.    <aop:pointcut id="IOpenApiOrderItemService"  
    24.     expression="execution(* com.alibaba.itbu.billing.api.collect.IOpenApiOrderItemService.*(..))" />   
    25.    <aop:pointcut id="IOpenApiBillingCollectService"  
    26.     expression="execution(* com.alibaba.itbu.billing.api.collect.IOpenApiBillingCollectService.*(..))" />   
    27.    <aop:pointcut id="IOpenApiInvoiceService"  
    28.     expression="execution(* com.alibaba.itbu.billing.api.invoice.IOpenApiInvoiceService.*(..))" />   
    29.    <aop:pointcut id="IOpenApiChargeProductInfoService"  
    30.     expression="execution(* com.alibaba.itbu.billing.api.collect.IOpenApiChargeProductInfoService.*(..))" />       
    31.    <!-- 配置advice,这里采用在业务方法执行前后进行拦截 -->    
    32.    <aop:around method="logExecuteTime" pointcut-ref="EsbPriceService" />  
    33.    <aop:around method="logExecuteTime" pointcut-ref="EsbProductService" />  
    34.    <aop:around method="logExecuteTime" pointcut-ref="IAuthorizeControllerService" />  
    35.    <aop:around method="logExecuteTime" pointcut-ref="IOpenApiOrderItemService" />  
    36.    <aop:around method="logExecuteTime" pointcut-ref="IOpenApiBillingCollectService" />  
    37.    <aop:around method="logExecuteTime" pointcut-ref="IOpenApiInvoiceService" />  
    38.    <aop:around method="logExecuteTime" pointcut-ref="IOpenApiChargeProductInfoService" />  
    39.   </aop:aspect>               
    40.  </aop:config>    
    41.   
    42. </beans>   

    我是基于配置完成AOP接入,这样做的好处是不需要对原有主流程代码有任何浸入,并且也比较容易移除本AOP的拦截,这段代码主要就是配置aspect、pointcut和advice

    3)编写监控耗时的advice

    OpenApiLogAspect:

    1. public class OpenApiLogAspect {  
    2.  private static LoggerService logger = LoggerFactory.getLogger(OpenApiLogAspect.class);  
    3.  public Object logExecuteTime(ProceedingJoinPoint joinPoint) throws Throwable{  
    4.   Date start = new Date();  
    5.   try{  
    6.    return joinPoint.proceed(joinPoint.getArgs());  
    7.   }catch(Exception err){  
    8.    throw err;  
    9.   }finally{  
    10.    Date end = new Date();  
    11.    logger.info("OpenApiExecuteTime:"+joinPoint.getSignature().getName()+" takes "+(end.getTime()-start.getTime())+"ms");  
    12.   }  
    13.  }  
    14. }   

    此段代码就是基于around的方式来拦截接口调用,在实际调用的前后加上时间记录,并最后在日志里打印出时间差。其中joinPoint.proceed(joinPoint.getArgs());是对实际接口的调用。

    4)使监控可以配置化

    此功能只会在调试阶段使用,并不需要在生产环境中运行,因此需要可以配置是否监控接口。实施这个配置化很简单,只需要通过配置决定是否把aop spring的配置文件加入到容器里就可以了,因此在总容器applicationContext.xml.vm里加上如下代码:

    #if(${monitor_openapi_showTime}=="true")  <import resource="classpath*:bean/billing-spring-aop.xml" />  #end

    在编译打包过程中会根据变量monitor_openapi_showTime来决定是否把billing-spring-aop.xml引入进来

    5)运行效果

    在监控开启的情况下,若发生接口调用,能从日志里看到如下记录:

    2010-01-08 18:30:13,197 [OpenApiLogAspect.java:20] [com.alibaba.itbu.billing.framework.aop.OpenApiLogAspect] INFO  com.alibaba.itbu.billing.framework.aop.OpenApiLogAspect :: OpenApiExecuteTime:installOrderItem takes 71ms 2010-01-08 18:30:27,188 [OpenApiLogAspect.java:20] [com.alibaba.itbu.billing.framework.aop.OpenApiLogAspect] INFO  com.alibaba.itbu.billing.framework.aop.OpenApiLogAspect :: OpenApiExecuteTime:installOrderItem takes 0ms 2010-01-08 18:30:37,838 [OpenApiLogAspect.java:20] [com.alibaba.itbu.billing.framework.aop.OpenApiLogAspect] INFO  com.alibaba.itbu.billing.framework.aop.OpenApiLogAspect :: OpenApiExecuteTime:installOrderItem takes 1ms

  • 相关阅读:
    MS面试归来:)
    准备出发到成都
    线程的同步机制(zz)
    Windows Vista(zz)
    这几天上海热晕了
    微软官方:Vista硬件要求指南(zz)
    有趣的递归缩写(Recursive acronym)
    《三国志》生僻人名读法集(zz)
    Git bash常用命令
    各大输入法分类词库内部格式的简单比较
  • 原文地址:https://www.cnblogs.com/huidaoli/p/3231513.html
Copyright © 2011-2022 走看看