zoukankan      html  css  js  c++  java
  • 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) { /** 监控逻辑处理错误什么都不做 */ } } }
  • 相关阅读:
    LVS+KEEPALIVED(2/3)
    LVS+KEEPALIVED(1/3)
    DRF之权限源码详解
    DRF认证之源码详解
    Django REST framework之JWT
    Restful_Framework之插件
    求两个有序数组的中位数,要求时间复杂度log(m+n)
    Django_Restful_Framework视图与路由
    Django_Restful_Framework
    restFul接口设计规范
  • 原文地址:https://www.cnblogs.com/sealedbook/p/6065343.html
Copyright © 2011-2022 走看看