想聊一聊流量控制,谈谈的重要性,解决了哪些业务问题,那我们问题来进入正题。
 
1、WEB容器如何流量控制?
 
一个Tomcat的容器,这个容器呢,部署在一台服务器上面,同时这台服务器的资源非常非常有限,这台服务器只能同时让500个请求访问,若是多余500个的话,这样服务器的资源就会打满,那么我们肯定需要想办法这些问题的。Tomcat本身就有这样的机制,因为每一个请求过来后,tomcat会为这个请求分配一个处理线程,所以tomcat就是来控制处理线程的数量。
server.xml
<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
connectionTimeout="8000"
enableLookups="false"
acceptorThreadCount="1"
URIEncoding="utf-8"
redirectPort="443"
compression="on" compressionMinSize="1024" compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain,application/json,application/xml" /> <Executor className="StandardThreadExecutor" name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="500" minSpareThreads="100"/>
 
maxThreads="500" 表示最多能同时并存500个处理线程。
acceptCount="500" 表示在500个处理线程在占用的情况中,还允许500个请求的排队。
这两个参数基本就是Tomcat在线程保护当中的策略。
 
 
2、一个WEB容器里面如何进行具体的业务模块的线程保护呢?
 
一个业务系统部署在一个Tomcat中,例如这个业务系统有两个重要模块(A和B模块),这个两个模块的请求都需要有资源处理,而不是那一个模块把系统的资源都占用去,例如:A模块限制最多300请求,B模块最多300个请求。这样场景的出现时,我们就需要考虑说A模块最多只能有300个处理线程,B也是这样,那么Tomcat是可以保证资源层面的,A+B共有500个,而无法确保A/B各300个,所以有如下想法:
 
1、每个请求进来确定是属于A还是属于B。
2、当前正在运行的A/B模块的数量。
 

 
 
基于上面想法的具体实现:
 
流量控制的业务实现(TrafficControl.java):
/**
* 简单的实现基于URL的流控
*/
public class TrafficControl { //一个url请求的最大访问数量为300
private final static int ONE_URI_MAX_CONCURRENT = 300;
//所有url请求的最大访问数量为500
private final static int ALL_URI_MAX_CONCURRENT = 500; private final static AtomicInteger all_url_concurrent = new AtomicInteger(0); private final static ConcurrentMap<String, AtomicInteger> url_concurrent_map = new ConcurrentHashMap<String, AtomicInteger>(); private final static SwitcherManager switcherManager = SwitcherManagerFactoryLoader.getSwitcherManagerFactory().getSwitcherManager(); private final static Switcher tcEnabled = switcherManager.registerSwitcher("feature.trackurl.traffic_control.enable", true); public static boolean isDisabled() {
return tcEnabled.isClose();
} public static boolean isOverflow(String uri) {
if (all_url_concurrent.get() > ALL_URI_MAX_CONCURRENT) {
return true;
}
AtomicInteger one_url_concurrent = url_concurrent_map.get(uri);
if (one_url_concurrent != null && one_url_concurrent.get() > ONE_URI_MAX_CONCURRENT) {
return true;
}
return false;
}
public static void startAccess(String uri) {
all_url_concurrent.incrementAndGet();
AtomicInteger one_url_concurrent = url_concurrent_map.get(uri);
if (one_url_concurrent != null) {
one_url_concurrent.incrementAndGet();
} else {
url_concurrent_map.putIfAbsent(uri, new AtomicInteger(1));
}
}
public static void endAccess(String uri) {
all_url_concurrent.decrementAndGet(); AtomicInteger one_url_concurrent = url_concurrent_map.get(uri);
if (one_url_concurrent != null) {
one_url_concurrent.decrementAndGet();
}
}
public static void dumpWarnLog() {
String lineSeparator = System.getProperty("line.separator");
// 估算每一个URL和其计数占用32个字符
StringBuilder sb = new StringBuilder((1 + url_concurrent_map.size()) * 32);
sb.append("all_url_concurrent : ").append(all_url_concurrent);
for (Map.Entry<String, AtomicInteger> entry : url_concurrent_map.entrySet()) {
sb.append(lineSeparator).append('\t').append(entry.getKey()).append(" : ").append(entry.getValue());
}
ApiLogger.warn(sb);
} }
 
Servlet的实现(TrafficControlServlet.java):
/**
* 带有流量控制的Servlet
*/
public class TrafficControlServlet extends HttpServlet { @Override
protected final void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if (TrafficControl.isDisabled()) {
super.service(req, resp);
return;
}
String uri = req.getRequestURI();
if (TrafficControl.isOverflow(uri)) {
TrafficControl.dumpWarnLog();
resp.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
return;
}
try {
TrafficControl.startAccess(uri);
super.service(req, resp);
} finally {
TrafficControl.endAccess(uri);
}
} }
 最后执行Servlet如下,继承于TrafficControlServlet。

public class TestServlet extends TrafficControlServlet {
private static final long serialVersionUID = 2895590140869067830L;
@Override
protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws IOException {
//.................
} @Override
protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws IOException {
doGet(request, response);
}
 

浅谈Web的流量控制的更多相关文章

  1. 【架构】浅谈web网站架构演变过程

    浅谈web网站架构演变过程   前言 我们以javaweb为例,来搭建一个简单的电商系统,看看这个系统可以如何一步步演变.   该系统具备的功能:   用户模块:用户注册和管理 商品模块:商品展示和管 ...

  2. 浅谈web应用的负载均衡、集群、高可用(HA)解决方案(转)

    1.熟悉几个组件 1.1.apache     —— 它是Apache软件基金会的一个开放源代码的跨平台的网页服务器,属于老牌的web服务器了,支持基于Ip或者域名的虚拟主机,支持代理服务器,支持安 ...

  3. [原创]浅谈Web UI自动化测试

    [原创]浅谈Web UI自动化测试 Web UI自动化测试相信大家都不陌生,今天来谈谈这个,我最早接触自动化测试时大约是在2004年,2006年当时在腾讯财付通算是开始正式接触自动化测试,之所以是正式 ...

  4. 浅谈|WEB 服务器 -- Caddy

    浅谈|WEB 服务器 -- Caddy 2018年03月28日 12:38:00 yori_chen 阅读数:1490 标签: caddyserverwebhttps反向代理 更多 个人分类: ser ...

  5. 浅谈 Web 中前后端模板引擎的使用

    前言 这篇文章本来不打算写的,实话说楼主对前端模板的认识还处在非常初级的阶段,但是为了整个 源码解读系列 的完整性,在深入 Underscore _.template 方法源码后,觉得还是有必要记下此 ...

  6. 浅谈WEB前后端分离

    重审业务逻辑 用过MVC的童鞋都知道业务逻辑(Bussiness Logic),但是大多对这概念又是模棱两可,业务逻辑从来都是这样难以理解,谈论前后端分离之前这个概念非常有必要探讨一下! 在简单的CR ...

  7. 浅谈WEB安全性(前端向)

    相信进来的时候你已经看到alert弹窗,显示的是你cookie信息(为配合博客园要求已删除).单纯地在你的客户端弹出信息只是类似于迫使你在自己的房间脱衣服——没人看得到,自然也不算啥恶意行为.那么如果 ...

  8. 【转载】拒绝平庸——浅谈WEB登录页面设计

    用户活跃度是检验产品成功与否的重要指标之一,传统行业的商家极为重视门面的装潢,因为一个好的门面可以聚集人气,招揽更多的顾客.古时候的大户人家院子门口的石狮子或其他的摆件的摆放极为讲究,有一定的风水学说 ...

  9. 拒绝平庸——浅谈WEB登录页面设计

    用户活跃度是检验产品成功与否的重要指标之一,传统行业的商家极为重视门面的装潢,因为一个好的门面可以聚集人气,招揽更多的顾客.古时候的大户人家院子门口的石狮子或其他的摆件的摆放极为讲究,有一定的风水学说 ...

随机推荐

  1. struct和typedef struct在c++中的用法

    #include<iostream> using namespace std; struct test{ int a; }test; //定义了结构体类型test,声明变量时候直接test ...

  2. sqrt()平方根计算函数的实现1——二分法

    C语言标准库: http://www.cplusplus.com/reference/cmath/ 在一个区间中,每次拿中间数的平方来试验,如果大了,就再试左区间的中间数:如果小了,就再拿右区间的中间 ...

  3. 一文让你从此告别HTTP乱码(一)Request篇

    #circle { background-color: #8fcbec; border: 3px } 概述 开发Web项目的过程中,经常遇到浏览器中显示的内容乱码,或者服务器获取浏览器请求参数时乱码的 ...

  4. iOS开发之transform

    transform主要应用于动画 1.让一个按钮每次向上移动100的距离 UIButton *head = (UIButton *)[self.view viewWithTag:10]; head.t ...

  5. zabbix_agent-linux下的安装

    scp 10.25.133.184:/usr/local/zabbix-2.4.1.tar.gz /usr/local 1.为了安全考虑zabbix只使用普通用户运行,假如你当前用户叫ttlsa,那么 ...

  6. 一个基于php+mysql的外卖订餐网站(带源码)

    订饭组 一个基于php+mysql的外卖订餐网站,包括前端和后台.源码地址 源码演示地址:http://dingfanzu.com 商家后台系统:http://dingfanzu.com/admin ...

  7. 《Django By Example》第十二章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:第十二章,全书最后一章,终于到这章 ...

  8. [Android]使用RecyclerView替代ListView(四:SeizeRecyclerView)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:<> [Android]使用RecyclerView替代ListView(四:SeizeRecyclerView) 在RecyclerV ...

  9. 老李推荐:第5章3节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 启动脚本

    老李推荐:第5章3节<MonkeyRunner源码剖析>Monkey原理分析-启动运行: 启动脚本   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性 ...

  10. 玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化

    一.创建 SSMVCAnnoDemo 项目 点击菜单,选择“File -> New Project” 创建新项目.选择使用 archetype 中的 maven-quickstart 模版创建. ...