zoukankan      html  css  js  c++  java
  • 【Java】关于项目启动大请求量高负载时如何确保db等资源不出错的问题

    还记得当时来现在这家公司面试时, 有过一个问题:
    如果一个项目启动时(单机), 瞬间来了1000个访问, 如何确保db等资源不会压垮呢?

    现在想想我当时回答的并不好, 而现在看公司框架才发现其实有针对于这一块做过专门的优化的。
    下面就来分享下公司关于这个地方的处理, 一句话总结就是:项目启动时会先热身一段时间,概率性拒绝请求以保证服务的高可用。

    下面直接说原理:
    1, 根据自己的业务需求设置一个热身时间:warmupTime
    2, 在服务启动接收请求的时候添加一个拦截器,如果项目还没有热身完就概率性停止对外服务。(这里使用random去计算时候返回正常的响应)
    3, 等热身完毕的时候提供完整的响应。

    使用场景:
    特别适用于单机服务(双机因为有负载均衡所以不必考虑这个问题),且并发较高的服务。使用热身的主要原因是:当系统初始化时缓慢增加请求,防止系统开始压力过大导致db等资源出错。

    下面直接贴代码, 用代码来讲解:

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        processRequest(req, resp);
    }
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        processRequest(req, resp);
    }
    
    protected void processRequest(HttpServletRequest requestOld, HttpServletResponse response) throws ServletException, IOException {
        // 当系统初始化时缓慢增加请求,防止系统开始压力过大导致db等资源出错
    if (!bootHandler.isOk() && bootHandler.handle(requestOld, response,               config)) {
            return;
        }
        
        //...
    }
    

    在接收到请求时会先去判断是否热身完毕, bootHandler.handle就是判断热身的方法,具体判断方式如下代码:

    public boolean handle(HttpServletRequest request, HttpServletResponse response, MvcConfig config) throws IOException {
        long warmupTime = config.getWarmupTime();
        String startingUpJson = config.getStartingUpJson();
        if (warmupTime <= 0) {
            ok = true;
        } else {
            long now = System.currentTimeMillis();
            if (startTime == -1 || startTime == 0) {
                if (startTime == -1) {
                    startTime = now;
                    LOG.info("收到第一个请求,开始进行热身");
                }
                RenderUtils.renderJson(request, response, startingUpJson);
                return true;
            } else {
                //从开始时间到现在,以及配置的热身时间计算当前服务的比例
                if (now >= startTime + warmupTime) {
                    ok = true;
                } else {
                    //比率是从 [0-100)
                    int rate = (int) ((now - startTime) * 100 / warmupTime);
                    boolean rejected = random.nextInt(100) > rate;
                    if (rejected) {
                        if (now - lastLogTime.get() > 1000L) {
                            lastLogTime.set(now);
                            LOG.warn("当前请求被拒绝,当前响应概率为:{}%", rate);
                        }
                        renderJson(request, response, startingUpJson);
                        return true;
                    }
                }
            }
        }
        return false;
    }
    

    首先回去判断是否配置了热身时间, 如果没有配置那么直接返回。
    接着就去用当前的时间和项目启动时间以及热身时间计算出比率, 然后通过random去判断当前请求是否返回响应。直到热身完, 比率会达到100%。

    下面贴一张项目启动时的Log:

    虽然这是一种很简单的方式处理项目启动时资源不可用的解决方法, 但是却对项目启动时带来很大的帮助, 希望这种方法能够对大家有用。

  • 相关阅读:
    飞入飞出效果
    【JSOI 2008】星球大战 Starwar
    POJ 1094 Sorting It All Out
    POJ 2728 Desert King
    【ZJOI 2008】树的统计 Count
    【SCOI 2009】生日快乐
    POJ 3580 SuperMemo
    POJ 1639 Picnic Planning
    POJ 2976 Dropping Tests
    SPOJ QTREE
  • 原文地址:https://www.cnblogs.com/wang-meng/p/7259790.html
Copyright © 2011-2022 走看看