系统性能监控系列1:使用JAVA动态代理实现非侵入式的性能测量方法
2016-10-16 17:11
756 查看
当我们开发的服务上线后,线上的系统运行状态(是否正常,性能是否满足需求)等等就成了架构师和研发工程师关心的问题 。对于系统监控有很多维度,比如:监控CPU,磁盘IO,监控服务请求的响应时间等。相对于这些来说,我今天要给大家分享的是具体的代码层次的性能测量。
有过一定开发经验的朋友,在代码遇到性能问题的时候,需要对代码进行性能测量。一般的方法是:在调用每一个目标方法是启动性能监视,在目标方法结束后计算执行时间并输出到console或者是log中,以遍进行代码性能的分析。我们首先讨论侵入式性能测量方法。
一、侵入式性能测量方法:
我们在进行业务开发的时候通常会设计一个业务接口,然后在让具体实现类继承接口,实现具体的业务功能。这里我定义了一个UserService接口如图下
下面我们来看下UserService接口的具体实现类,如下图所示:
图1
PerformanceMonitor工具类的定义如下:
图2
如果要想测量doSomething的执行性能,我们需要在doSomething的方法中加入性能测量代码(如图1红框中代码所示)。当我们有很多的函数需要测量,那么像如上图1所示UserServiceNoPorxyImpl的实现的话,我们需要做很多的重复工作,需要把对PerformanceMonitor的调用复制到所有需要测量的函数内部。这是一个繁琐而且没有工作效率的事情。最恐怖的是,这些代码掺杂在正常的业务代码中,影响后期系统维护。那么有没有好办法解决这个问题呢?答案是有。
二、JAVA的动态代理机制性能测量方法
动态代理是JDK1.3之后提供的开发技术,它允许开发者在程序运行期间创建接口的代理实例。JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler。InvocationHandler是一个接口。可以通过实现该接口进行性能测量方法。关于动态代理的具体细节请大家Google下。在这里就不赘述了。
首先我们删除了doSomething中的性能测量代码,如下所示:
图3
从上图中可以看出,改写后的UserService实现类中方法doSomething中已经将性能测量代码都去掉了,只剩下业务逻辑代码,是不是很清爽?
那么问题来了,既然doSomething中没有了性能测量代码,我们怎么能够实现具体的性能测量呢。这是我们就需要InvocationHandler接口的帮助了,我们将性能测量代码实现在InvocationHandler接口的实现类PerformanceHandler中,代码如下图所示:
PerfomaceHandler关键所在如上图中③所示(调用业务目标的方法,在我们这里就是调用doSomething方法)。
具体调用过程如图3红框中所示,我们需要使用到Proxy类的newProxyInstance静态方法来动态创建一个UserService的代理接口。该方法的第一个参数是类加载器,第二个参数是创建代理实例所需要实现的一组接口,第三个参数是InvocationHandler。
通过测试,我们发现上述代码和侵入式性能测试代码的效果一致。我们通过使用JAVA的动态代理机制我们把性能测试代码和业务逻辑代码解耦。
有过一定开发经验的朋友,在代码遇到性能问题的时候,需要对代码进行性能测量。一般的方法是:在调用每一个目标方法是启动性能监视,在目标方法结束后计算执行时间并输出到console或者是log中,以遍进行代码性能的分析。我们首先讨论侵入式性能测量方法。
一、侵入式性能测量方法:
我们在进行业务开发的时候通常会设计一个业务接口,然后在让具体实现类继承接口,实现具体的业务功能。这里我定义了一个UserService接口如图下
下面我们来看下UserService接口的具体实现类,如下图所示:
图1
PerformanceMonitor工具类的定义如下:
图2
如果要想测量doSomething的执行性能,我们需要在doSomething的方法中加入性能测量代码(如图1红框中代码所示)。当我们有很多的函数需要测量,那么像如上图1所示UserServiceNoPorxyImpl的实现的话,我们需要做很多的重复工作,需要把对PerformanceMonitor的调用复制到所有需要测量的函数内部。这是一个繁琐而且没有工作效率的事情。最恐怖的是,这些代码掺杂在正常的业务代码中,影响后期系统维护。那么有没有好办法解决这个问题呢?答案是有。
二、JAVA的动态代理机制性能测量方法
动态代理是JDK1.3之后提供的开发技术,它允许开发者在程序运行期间创建接口的代理实例。JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler。InvocationHandler是一个接口。可以通过实现该接口进行性能测量方法。关于动态代理的具体细节请大家Google下。在这里就不赘述了。
首先我们删除了doSomething中的性能测量代码,如下所示:
图3
从上图中可以看出,改写后的UserService实现类中方法doSomething中已经将性能测量代码都去掉了,只剩下业务逻辑代码,是不是很清爽?
那么问题来了,既然doSomething中没有了性能测量代码,我们怎么能够实现具体的性能测量呢。这是我们就需要InvocationHandler接口的帮助了,我们将性能测量代码实现在InvocationHandler接口的实现类PerformanceHandler中,代码如下图所示:
PerfomaceHandler关键所在如上图中③所示(调用业务目标的方法,在我们这里就是调用doSomething方法)。
具体调用过程如图3红框中所示,我们需要使用到Proxy类的newProxyInstance静态方法来动态创建一个UserService的代理接口。该方法的第一个参数是类加载器,第二个参数是创建代理实例所需要实现的一组接口,第三个参数是InvocationHandler。
通过测试,我们发现上述代码和侵入式性能测试代码的效果一致。我们通过使用JAVA的动态代理机制我们把性能测试代码和业务逻辑代码解耦。
相关文章推荐
- JAVA动态代理和方法拦截(使用CGLib实现AOP、方法拦截、委托)
- 动态代理(1,umeng 自定义事件的统计,2,非侵入式的性能测量方法 )
- Java使用注解和动态代理实现方法调用时的日志记录示例
- JAVAWEB开发之Servlet3.0新特性的使用以及注解的详细使用和自定义注解的方法、动态代理的使用、利用动态代理实现细粒度的权限控制以及类加载和泛型反射
- JAVA动态代理和方法拦截(使用CGLib实现AOP、方法拦截、委托)
- 使用Java 动态代理实现AOP
- 使用Java动态代理实现AOP
- AOP系列之三:用Java动态代理实现AOP [zz]
- Java初学者如何迈出AOP第一步--使用Java 动态代理实现AOP(转)
- 使用JAVA中的动态代理实现数据库连接池
- Java初学者如何迈出AOP第一步--使用Java 动态代理实现AOP
- AOP系列之三:用Java动态代理实现AOP
- 迈出AOP第一步--使用Java 动态代理实现AOP[zz]
- 使用JAVA中的动态代理实现数据库连接池
- 使用JAVA的动态代理实现数据库连接池
- 使用Java的动态代理技术实现对象适配器模式
- Java初学者如何迈出AOP第一步--使用Java 动态代理实现AOP
- 使用JAVA中的动态代理实现数据库连接池
- 使用Java 动态代理实现AOP
- 使用JAVA中的动态代理实现数据库连接池