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) { /** 监控逻辑处理错误什么都不做 */ } } }

 

posted @ 2016-12-17 19:33  天书说  阅读(12791)  评论(0编辑  收藏  举报