周末,多动程序员自然是闲不住的,调试一下代码,发现在使用了guava cache的代码在每次调用的时候都会重新load一次,也就是缓存没生效,每次都会再请求一次后台,本着CV至上的精神,老子从别的地方copy来的代码,怎么会出错呢,不能忍!
排查思路:继续debug
1. 难道新生成的key在hash的时候计算出来的值不一样?调试两次,发现是一样的(肯定是一样的,自己找个心里安慰,以为发现重大bug)
2. 在上面两次调试的过程中发现第二次请求来的时候,缓存对象localCache = null,难道获取的值没有set进去?再调试一次,发现set到缓存了(肯定会set进缓存,不然这个组件还怎么用。。。)
3. 找到copy代码的类,调试一下,发现同样的效果,以前别人加的缓存岂不是一直没有用。为什么在别的项目用的好好的,放在这里就不行了呢
4. 这个时候想到,难道缓存对象不是static?每次调用会生成一个新的对象?(已经接近真相),看了下代码使用,确实不应该是static,那就是bean非单例,,,每次调用会生成一个新的bean
5. 于是再调试两次,发现每次都会生成一个新的bean,那bean里的缓存对象localCache自然也是null(问题根源)
6. 为什么会非单例,Bean继承了org.restlet.resource.ServerResource类,古老的项目使用的是restlet + spring的结构,同struts,每次调用会生成一个新的bean,spring mvc是单例的。
7. 缓存代码提取出来,放到servcie里
总结:
1. 第1,2两步是最直接也是最蠢的想法,也是潜意识里会把最直接的解决问题的办法搬出来,然后在后续的排查和分析中才逐渐找到问题的根源
2. 由于是很古老的代码,自己懒省事,直接把缓存代码放到了最外层(action/controller)(老代码就是这样用的),而不是封装到service层
3. c v 有风险,调试需谨慎,代码不规范,debug两行泪
网友评论