面试题:假如一个线上的Java服务,堆内存只设置了2G,普通情况下请求很少,系统没什么问题,但是突然有一天下游系统故障引起 了大量的请求堆积在这个服务,这个时候这些剧增的流量是如何打垮这个服务的?
面试题常规回答
应该是大量的对象来不及处理,直接进入了老年代,然后老年代频繁触发GC,导致出现了系统的卡死。
面试题深入剖析
我们举个例子来说明一下,系统的堆内存是2GB,假设新生代占了512MB,剩下的是老年代的。
一般情况下,假设高峰期每秒大概100个请求,对应请求对象有100个创建出来,每个请求对象占据500左右的字节大小,总共就是50kb左右。
然后一个请求大概要1秒来处理,所以这100个对象在新生代中存在1秒的期间会被人引用,是无法被回收的。
当然,由于系统为了处理一个请求,肯定还需要创建很多其他的对象才能完成整个流程。比如一个登陆请求,我们还需要从数据库查询是否存在该用户,这里的查询条件、查询结果和判断值等等,都是需要创建对象并且占用内存的。所以在上面的50kb的基础需要扩大10倍~20倍。
所以我们就扩大20倍好了,那么基于上面的过程,在1秒之内,总共会创建出来大概1MB左右的对象,无法被回收。
其实按照上面估算的内存压力,512MB的新生代在系统正常运行的情况下,其实还不算什么大问题。
因为每秒新增1MB对象,然后几百秒过后,新生代快满了