JVM的FullGC优化实战(二)

上一篇文章,分析了导致GC的原因:内存中持有了大量的session。当时查代码比较粗心,竟没有看到一些显式使用session的地方。业务是这样的:在请求到来时,根据用户请求信息(如ip),获取用户所在地区,然后将该dp信息放到session中,后面Controller直接拿来使用,不必在进行判断。

    先看地区Filter:

public class DqFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        final HttpServletRequest request = (HttpServletRequest) servletRequest;
        final HttpServletResponse response = (HttpServletResponse) servletResponse;
	//...
	//获取地区代码
        String dq = getDqCode(request);
        //将地区信息放到session中
	request.getSession().setAttribute("dqs", dq);
        //...
        filterChain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
    }

    /**
     * 
     * @param request
     */
    private String getDqCode(HttpServletRequest request) {
	String dq = ...;//获取地区信息
        return dq;
    }
}

       再看Controller中:

@Controller
@RequestMapping(value = "/xxx")
@SessionAttributes("dqs")
public class QiuzhiController extends BaseController {

    @RequestMapping()
    public String execute(... @ModelAttribute("dqs") String dq...)
            throws Exception {
	//获取dq信息
        return "index";
    }

}

 

    coding作者的本意,可能是想节省根据ip获取dp信息的开销,因此创建一个session把这个信息放进去。但确实弄巧成拙了,每一次会话,都会往里面放东西,积少成多。

    其实还有另外一个“祸手”加重了问题的严重性。我们的系统架构,通过在项目根目录下放置一个ok.html来做心跳检测,访问成功就认为服务在,不通就认为服务死,但这个检测机制有一个大问题,即不是针对工程,而是针对域名。由于该项目是城市站,对应了n个城市二级域名,如bj.demo.com、sh.demo.com......因此访问量相当于自身真实访问量的n倍,具体到我们这里,可能就是100倍,以至于流量的99%就是心跳,每小时上千万的pv。

    那这些心跳会导致什么呢?没错,由于Filter的url-pattern配置的是/*,因此ok.html请求也能进来,而这个请求,只是一个curl简单请求,不会携带cookies,亦不会携带jsessionid,好了,每次请求都会创建一个session,并往会话中存放这个地区信息。

    鉴于上面的分析,笔者把使用Session的地方都删掉,改用request.setAttribute,其实request也没有必要,因为获取地区信息本身也不太耗费性能。

    下面是当前的JVM的GC情况:

JVM的FullGC优化实战(二)_第1张图片

    没有GC了。

    再看下JVM堆内存:

JVM的FullGC优化实战(二)_第2张图片

    非常平稳了!

    

    总结:

    互联网项目不同于普通的后台系统,访问量巨大,即便没有上面的心跳,这个问题尽早也会因为某种原因,如(大量的爬虫抓取行为)而产生恶劣的影响。所以要禁用session。

你可能感兴趣的:(java,线上故障)