问题概述:
公司做的是BS应用。
之前我们的后台服务器程序是带状态的,用ehcache存储登录状态;这两天被我改成了redis存储,应用本身不再存储登录状态。
然后自测,我在测试某个很耗时间的网页操作的时候,发现第一次请求的时候还比较快(这个请求会开200个iframe出来,每个iframe内部还有2个ajax请求)(期间浏览器会向服务器发送了大概600个请求),耗时1分钟内;
然后第二次请求的时候,发现很多请求一直处于pending状态(chrome的开发者工具可以看),等待很久也出不来页面,就是一直转圈加载,很有耐心的我等了10多分钟才出来。
先是用chrome的开发者工具查看请求,以下面的一个ajax请求为例,
从开发者工具看到右边的主要耗时在Waitting(TTFB),那看来应该是我服务器有问题咯?
排查开始:
1、后台逻辑
这个请求的主要逻辑是:先过拦截器,拦截器根据cookie中带的全局token去redis取登录信息,判断是否登录来进行拦截;如果登录了的话,到controller层后,主要是查数据库,为了排除这部分影响,业务代码被我注释了,直接返回。
2、排除无关因素
2.1、先注释掉业务逻辑代码
2.2、再记录下拦截器中从redis取数据花费时间:
3、跑了几把后,日志记录大概如下:
因为是业务逻辑马上就返回,几乎不耗时;
拦截器也耗时很少,大概是0,1,2这几个值(局域网redis还挺快的)
4、开始问题测试
结果呢,发现现象还是一样,第一次还比较快,后面就越来越慢。开始怀疑是不是tomcat的问题,
于是尝试改成了nio、线程数也加大了
(上图默认的http11,没换成nio,要换的话,改成org.apache.coyote.http11.Http11NioProtocol)
参考:http://www.jianshu.com/p/8445645b3aff
5、加大tomcat线程池后的结果
还是差不太多,就是比之前是快了一点的感觉。
6、后边跟同事一起分析的时候,同事说要不你把tab页关了再试试,受到了启发。
第一次请求的时候,浏览器的该网站进程(因为chrome浏览器是每个tab页一个进程的)内存占用为600M;
第二次请求的时候,内存会飙到1200M左右;
第三次请求,貌似我那几百个请求几乎很多都在pengding状态。
下面是测试结果:
6.1、首次打开网站时,内存占用为70M
6.2、跑第一次耗时操作
第一次任务跑完,内存上到了1200M,耗时50s,共600个请求左右。
6.3、跑第二次耗时操作
。。。。
。。。。
。。。。
等得时间太长了,所以无聊中看了下任务管理器(上面说了,因为chrome的tab页是进程,所以可以看到)
内存已经快要到1800M了。
开发者工具如下:
可以发现有大量的pending请求,然后时间也已经过去了好几分钟(快6分钟了,还没有完结的迹象)
此时的服务器后台如何呢?
拦截器和业务逻辑方法依然很快。
。。。。
。。。。
。。。。
等啊等
终于,在700s,也就是11分钟左右,终于结束了。坑啊
6.4、对页面刷新后,再跑一次试试
F5刷新后,看看内存占用:
200M。还可以
那么我们再跑一次看看效果
可以看到,新的一次请求,在一分钟内结束了。
总结:事到如今,问题已经很明显,是浏览器tab页(进程)占用内存过大后,发送的请求中pending状态的请求的比例会显著增加。具体原因未明,望解惑。
解决的办法是F5刷新或者关掉tab页重新打开。