一.问题
循环调用同一个接口,调用100次,其中有95次或是98次都是几十毫秒返回,但是有那么几次一秒左右才返回。接口相同,参数相同,返回时间怎么差异这么大?这个问题困扰了我很长时间,经过一段时间的研究终于知道原因了,起初我猜测可能的原因如下:
1:难道是网络问题?
2:难道是缓存问题?
二.分析问题
1:网络延迟
服务同属于一个局域网,网络延迟不会超过5ms,所以不是网络延迟造成的。
2:没有命中缓存
如果没有命中缓存,也应该是第一个请求没有命中,后续的请求就会从缓存中拿数据了。(我使用的缓存策略是从关系型数据库中读取数据后,会写到redis中)
3:不是网络延迟,也不是缓存问题,那就只能是服务本身的问题,服务除了正常接收请求外,还会做一件很重要的事,那就是垃圾回收。因此查看了那个请求慢的时间点,再查看服务的垃圾回收记录,发现刚好一致。因此可以证明,偶发的请求慢,是因为遇到了垃圾回收。
三.获取垃圾回收信息
通过性能计数器来获取垃圾回收的信息,可以获取如下信息:
1:获取0代、1代、2代对象的回收次数
2:获取1代堆、2代堆和大对象堆大小
3:代码
-
获取一个实例名称(要监控对象)
-
根据类型名称、计数名称、实例名称创建新能计数器,并且获取垃圾回收次数(此处是获取1代对象的垃圾回收次数)
-
运行代码,查看结果。6 就代表了从服务启动以来,进行的1代对象的垃圾回收次数
四.实战
已经介绍了如何获取垃圾回收的信息,那么在实际工作当中如何应用呢,答案也很简单,只需要做两件事,如下:
1:服务要支持获取0代、1代、2代对象的回收次数的功能
2:间隔3秒或是5秒将回收次数存放到数据库中。当发现请求有延迟的情况,可以查看数据库中的数据,在那个时间点是否存在垃圾回收。
五.另外
也有可能是其他原因,请高手指点…