您的位置:首页 > 编程语言 > Java开发

Spring-AOP实践

2016-07-17 23:00 267 查看

Spring-AOP实践

公司的项目有的页面超级慢,20s以上,不知道用户会不会疯掉,于是老大说这个页面要性能优化。于是,首先就要搞清楚究竟是哪一步耗时太多。

我采用spring aop来统计各个阶段的用时,其中计时器工具为StopWatch。

文章结构:

遇到的问题

创建项目

AOP-HelloWorld

时间统计

bug

final

压力测试

源码

其中,遇到的问题:

1.少包aspectjweaver

添加依赖后才可以使用@Aspect

2.环绕通知加入多个point

刚开使用&&连接多个point,傻傻的看不到调用,忽然看到要用||才对

3.监听时间工具StopWatch每次只能启动一个,一定要关闭后才能启动下一个。

而我想要测试controller->service->repository各个阶段用时显然很不适应。因为使用同一个stopwatch对象来保存时间,而stopwatch每次只能记录一个时间段作为总时间的一部分,不存在时间嵌套关系(这个以后可以考虑想想别的方案)。controller开始后执行部分验证逻辑或是其他,然后调用service,这时候service启动定时会失败,因为controller的计时器还没关,因此需要先关掉controller的计时器。这样会导致controller的计时部分仅仅是调用service之前的时间,service返回值之后,controller再进行某些处理的时间并没有统计。显然,我需要一个卡表的时间统计设计,即进入controller开始计时,调用service后开始service计时,以此类推,最后获得controller总时间Tc,service总时间Ts,repository总时间Tr.所以时间统计应该如图1:

View Code

1.6这时候可以测试一下启动看看了

直接启动:运行com.test.spring.aop.Application#main()即可。

命令行启动:mvn spring-boot:run

命令行bug启动:mvn spring-boot:run -Drun.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"

1.7创建测试com.test.spring.aop.ApplicationTest

View Code

2.AOP - HelloWorld

2.1创建com.test.spring.aop.monitor.ServiceMonitor

View Code
2.2测试

测试水平还没开始,所以只能手动测试了,运行com.test.spring.aop.ApplicationTest可以看到在HelloService调用前后插入了日志。

3.时间统计

最终,生成类图如下:

View Code
3.2发现需要一个service

创建com.test.spring.aop.domain.service.IUserService

View Code
创建com.test.spring.aop.domain.service.impl.UserService

View Code
3.3发现需要一个repository

创建com.test.spring.aop.domain.repository.IUserDao

View Code
创建com.test.spring.aop.domain.repository.impl.UserDao

View Code
3.3.1临时添加一个远程调用

创建com.test.spring.aop.domain.repository.IConnector

View Code
创建com.test.spring.aop.domain.repository.impl.Connector

View Code

3.4发现需要一个实体类

创建com.test.spring.aop.domain.entiry.User

View Code
3.5完成

以上就基本把一个web接口搞定了,可以运行测试一下,使用浏览器或者postman访问localhost:8080/user/all就可以获得user列表了。

3.6加入user时间统计

创建com.test.spring.aop.monitor.UserMonitor

View Code
这里有几点问题:

1.StopWatch不能重复创建,如果想统计每次controller访问时间,必须在访问前初始化,访问后废除。

2.这里的时间统计仅仅针对controller入口的统计,也就是说,如果别的调用了service,这个时间是不统计的,因为StopWatch没有初始化。

3.StopWatch的prettyPrint是一个很好的东东

4.如果想要向开始那样,完全统计每层耗时,这个设计需要重新设计。当前有这样的想法。controller切点初始化三个或者多个StopWatch;service、repository等分别建立切点并计时;controller执行完毕之后的切点汇总统计数据,销毁各个StopWatch。这样就做到了每个层都统计了。然而问题来了,如果一个controller调用了多个service,显然需要统计所有service耗时和单个service耗时。

View Code

压力测试

1.建立test case

首先,测试controller:创建com.test.spring.aop.web.UserControllerTest

View Code
不知道为啥,我的new Thread并没有并发执行,而是按顺序执行的。也就是说,虽然我new 10 个Thread,但还是一个接一个的运行。

改进
于是,我想采用线程池:

  

这下就可以看到controller是多线程并发的了,因为瞬间就打印了10条controller访问日志,正好是线程池的最大容量:

View Code

2.采用Apache 的ab进行并发访问

2.1下载Apache

参考:使用Apache Server 的ab进行web请求压力测试

2.2测试

View Code

可以看到服务端是多线程的:

View Code

项目源码:https://github.com/chenxing12/spring-aop
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: