Java接口響應超時監控


為什么要監控

  服務化接口是提供服務的,接口正確性、穩定性是最最重要的,在保證正確的同時需要盡量提高接口響應時間。

  有的團隊會有專門的工具來對系統響應時間、吞吐量做監控,但如果團隊沒有這種“待遇”就需要自己來做一些工具為自己的代碼提供服務。

自己動手,豐衣足食

  AOP + Annotation 簡陋實現,能達到目的

  AOP : 使用環繞方式對接口攔截,在攔截接口前后記錄時間最后計算用時

  Annotation : 自定義注解在接口上設置超時時間(timeout)和超時是否發送郵件選項(emailIfTimeout)

  通過對接口實際執行時間和配置的超時時間比較,系統可以計算出接口是否超時,此時可使用日志(或其他能通知到開發人員的方式)記錄具體哪個接口、什么參數以及執行時間

  注解可以提供更多的選項,來為自己接口服務,比如支持注解到類上,批量為接口設置了默認超時時間、支持日志中顯示的處理方法名稱 等等...

代碼實施

接口Annotation定義

/**
 * 接口自定義屬性
 *
 * @author tianshu on 16/8/30 下午4:55.
 */
@Target(value = {ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface InterfaceProperty {

    /**
     * 接口超時時間,單位毫秒.默認值100毫秒
     * @return 設置的超時時間
     */
    int timeout() default 400;

    /**
     * 當接口響應超時時,是否發送郵件.默認發送
     * @return 返回ture需要發送郵件
     */
    boolean emailIfTimeout() default true;
}

 

AOP實現

/**
 * @author tianshu on 16/1/28 下午10:35.
 */
@Component
@Aspect
public class SystemRequestAspect {

    /** 日志 */
    private static final Logger LOG = LoggerFactory.getLogger(SystemRequestAspect.class);

    /** 接口超時日志 */
    private static final Logger INTERFACE_TIMEOUT_LOG = LoggerFactory.getLogger("INTERFACE_TIMEOUT_LOG");

    @Around(value = "execution(* com.xx.xx.xx.xx..*.*(..))", argNames="pjp")
    public Object validator(ProceedingJoinPoint pjp) throws Throwable {
        Object[] args = pjp.getArgs();

        /** 攔截的方法名稱 */
        String methodName = pjp.getTarget().getClass().getSimpleName() + "." + pjp.getSignature().getName();

        try {
            long start = System.currentTimeMillis();
            Object obj = pjp.proceed(args);
            long finish = System.currentTimeMillis();
            long useTime = finish - start;
/** 接口響應時間監控 */ interfaceUseTimeMonitor(pjp.getTarget().getClass(), pjp.getSignature().getName(), args, useTime); return obj; } catch(Throwable e) {//處理你的異常 } finally {//處理其他 } } /** * 接口響應時間監控 * * @param targetClass 接口實現class * @param methodName 接口方法 * @param args 接口如參 * @param useTime 調用接口實際使用時間 */ private void interfaceUseTimeMonitor(Class targetClass, String methodName, Object[] args, long useTime) { /** 與接口注解最高用時做比較,符合條件發送郵件 */ try { Class[] classArray = new Class[args.length]; for(int i = 0; i < args.length ; ++i) { classArray[i] = args[i].getClass(); } Method method = targetClass.getMethod(methodName, classArray); if(method.isAnnotationPresent(InterfaceProperty.class)) { InterfaceProperty interfaceProperty = method.getAnnotation(InterfaceProperty.class); if(useTime >= interfaceProperty.timeout()) { if(INTERFACE_TIMEOUT_LOG.isInfoEnabled()) { INTERFACE_TIMEOUT_LOG.info("接口超時,interface:[{}].useTime:[{}].settingUseTime:[{}].traceId:[{}]", new Object[]{targetClass.getSimpleName() + "." + methodName, useTime, interfaceProperty.timeout(), TraceUtils.getTrace()}); } } } } catch(Throwable e) { /** 監控邏輯處理錯誤什么都不做 */ } } }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM