【Java】关于项目启动大请求量高负载时如何确保db等资源不出错的问题
2017-07-30 17:34
671 查看
还记得当时来现在这家公司面试时, 有过一个问题:
如果一个项目启动时(单机), 瞬间来了1000个访问, 如何确保db等资源不会压垮呢?
现在想想我当时回答的并不好, 而现在看公司框架才发现其实有针对于这一块做过专门的优化的。
下面就来分享下公司关于这个地方的处理, 一句话总结就是:项目启动时会先热身一段时间,概率性拒绝请求以保证服务的高可用。
下面直接说原理:
1, 根据自己的业务需求设置一个热身时间:warmupTime
2, 在服务启动接收请求的时候添加一个拦截器,如果项目还没有热身完就概率性停止对外服务。(这里使用random去计算时候返回正常的响应)
3, 等热身完毕的时候提供完整的响应。
使用场景:
特别适用于单机服务(双机因为有负载均衡所以不必考虑这个问题),且并发较高的服务。使用热身的主要原因是:当系统初始化时缓慢增加请求,防止系统开始压力过大导致db等资源出错。
下面直接贴代码, 用代码来讲解:
在接收到请求时会先去判断是否热身完毕, bootHandler.handle就是判断热身的方法,具体判断方式如下代码:
首先回去判断是否配置了热身时间, 如果没有配置那么直接返回。
接着就去用当前的时间和项目启动时间以及热身时间计算出比率, 然后通过random去判断当前请求是否返回响应。直到热身完, 比率会达到100%。
下面贴一张项目启动时的Log:
虽然这是一种很简单的方式处理项目启动时资源不可用的解决方法, 但是却对项目启动时带来很大的帮助, 希望这种方法能够对大家有用。
如果一个项目启动时(单机), 瞬间来了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:
虽然这是一种很简单的方式处理项目启动时资源不可用的解决方法, 但是却对项目启动时带来很大的帮助, 希望这种方法能够对大家有用。
相关文章推荐
- 问题解决-某些项目因位于工作空间目录中而被隐藏 & 如何解决java项目导入出错:与另一项目重叠
- intellij IDE build出错,无法显示图片,找不到tomcat server,java编译版本过低,异常推出后无法启动项目等常见问题解决
- 关于myeclipe的java web 项目如何更改项目名称的问题
- 关于项目中时常遇到的R资源出错问题
- 关于maven项目在引入java project 时,打war包出错的问题
- 如何启动一个liferay项目,如何获取资源
- 学习Java的第一步是安装好JDK,写一个Hello World, 其实JDK的学习没有那么简单,关于JDK有两个问题是很容易一直困扰Java程序员的地方:一个是CLASSPATH的问题,其实从原理上来说,是要搞清楚JRE的ClassLoader是如何加
- 关于vs2003调试时出错:“试图运行项目时出错:无法启动调试”解决
- 关于java和web项目中的相对路径问题
- 关于vs2003调试时出错:“试图运行项目时出错:无法启动调试”解决
- 关于HttpModule中像图片,*.css,*.js等资源文件也被请求问题的解决
- 关于vs2003调试时提示:试图运行项目时出错:无法启动调试 没有正确安装调试器。请运行安装程序安装
- 关于vs2003调试时出错:“试图运行项目时出错:无法启动调试”解决
- 关于在apache中发布项目,项目中引入资源的路径问题
- 关于vs2003调试时提示:试图运行项目时出错:无法启动调试 没有正确安装调试器。请运行安装程序安装
- 关于vs2003调试时出错:“试图运行项目时出错:无法启动调试”解决
- XP下如何解决“ASP.NET 未被授权访问所请求的资源”的问题
- 关于Eclipse启动出错的问题
- 常见问题:试图运行项目时出错:无法启动调试 没有正确安装调试器。请运行安装程序安装或修复调试器
- 关于vs2002调试时提示:试图运行项目时出错:无法启动调试 没有正确安装调试器。请运行安装程序安装或修复调试器