【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:

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏SDNLAB

数据中心工具———虚拟网络方案Calico初探

特点与对比 Calico是一个基于BGP协议的虚拟网络工具,在数据中心中的虚拟机、容器或者裸金属机器(在这里都称为workloads)只需要一个IP地址就可以使...

442150
来自专栏程序员的SOD蜜

“一切都是消息”--MSF(消息服务框架)入门简介

“一切都是消息”--这是MSF(消息服务框架)的设计哲学。 MSF的名字是 Message Service Framework 的简称,中文名称:消息服务框架,...

55750
来自专栏FreeBuf

一个和任天堂游戏机有关的0-day漏洞,可能对大多Linux系统造成影响

上个月,我们发布过一篇相关红白机的Ubuntu漏洞,利用恶意构建的红白机音乐文件就能触发——这是著名安全专家Chris Evans的杰作;实际上,超任也存在这种...

22050
来自专栏翻译

Universe入门

Universe是一个用于衡量和训练AI的软件平台,适合世界上的所有游戏,网站和应用程序。本项目是一个universe开源库,它为 每个Universe环境提供...

83660
来自专栏SDNLAB

SONiC-P4 image build解析

31570
来自专栏linux、Python学习

60个DevOps开源工具,你在用哪些?

你喜欢免费的东西吗?获得开发者社区支持的自动化,开源的工具是大家梦寐以求的。这里列举了 60 多款最棒的开源工具,可以帮助你很好的实行 DevOps。

18800
来自专栏IT派

Python | 查看微信撤回的消息(完整代码)

看到了一个基于python的微信开源库:itchat,玩了一天,做了一个程序,把私聊撤回的信息可以收集起来并发送到个人微信的文件传输助手,包括:

38720
来自专栏华章科技

撤回的微信消息真的看不到?78行Python代码帮你看穿一切!

导读:Python曾经对我说:"时日不多,赶紧用Python"。于是看到了一个基于python的微信开源库:itchat,玩了一天,做了一个程序,把私聊撤回的信...

7830
来自专栏FreeBuf

“撬锁”实战:绕过云锁提权某游戏私服

朋友给我了我一个游戏私服的shell,说是提权不下服务器,让我帮忙看看。本文仅为大家提供一个思路,这个方法可能很多人知道但是并没有公布到网络。我今天写出来只是为...

22150
来自专栏Grace development

PHP程序员如何简单的开展服务治理架构(二)

服务治理 治理的绝笔是服务,在一家公司有玩各种语言的程序员,如何去统一管理他们开发的服务,这是一个问题。

19520

扫码关注云+社区

领取腾讯云代金券