想聊一聊流量控制,谈谈的重要性,解决了哪些业务问题,那我们问题来进入正题。
 
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. 【CNMP系列】VIM编辑器详解

    缘起 大学的时候做过Linux内核驱动程序研发,之前写C语言就是用的Vim编辑器,当年的Vim还不如今天之强大,当时的插件也没有现在这么多,只是觉得这个编辑器能满足我想要的所有,查看Linux内核代码 ...

  2. Windows 10 IoT Serials 7 – 如何用树莓派制作家庭流媒体播放器

    Windows 10平台引入了AllJoyn开源软件框架,它提供了一组服务可以创建动态近端网络,让设备可以相互连接实现功能交互.目前,AllJoyn开源软件框架由AllSeen联盟负责管理.AllSe ...

  3. eclipse项目导入到android studio中文乱码处理

    由于eclipse项目是gbk编码,Android studio默认用的是utf-8. 就会导致代码中的汉字,注释全部显示为乱码. 解决方法:在module的bulid.gradle中加入: comp ...

  4. Windbg调试中遇到的问题

    1.找不到符号文件 抓取完Dump后,打开WinDbg,Ctrl+D找到刚才抓取的Dump文件,报如下异常: *** ERROR: Symbol file could not be found. De ...

  5. 微信小程序-实战巩固(二)

    刚刚写了小程序入门没几天,小程序就开放个人开发者资格,感觉为我而来啊 \(≧▽≦)/.迫不及待的去注册,准备将之前的处女作传上去体验一把,结果卡在了服务器配置上:免费的果然不靠谱/(ㄒoㄒ)/~~,后 ...

  6. Access中的自定义排序设置方式

    一.问题起因 最近有网友提问说,Access中在用查询指定排序方式时,为什么只有升序跟降序,怎么米有自定义排序了?竟然比Excel都弱啊! 其实这是对Access的误解,我这就给大家来解一下疑惑.案例 ...

  7. 关于html5调用手机相机(原创)

    很久没写随笔了 从ios6开始,webview支持html <input type="file">标签,用来调取手机的相册和相机,但是没有权限提示,不知道是不是我写的有 ...

  8. WebGL 创建和初始化着色器过程

    1.编译GLSL ES代码,创建和初始化着色器供WebGL使用.这些过程一般分为7个步骤: 创建着色器对象(gl.createBuffer()); 向着色器对象中填充着色器程序的源代码(gl.shad ...

  9. 01 The Learning Problem

    什么时候适合用机器学习算法? 1.存在某种规则/模式,能够使性能提升,比如准确率: 2.这种规则难以程序化定义,人难以给出准确定义: 3.存在能够反映这种规则的资料. 所以,机器学习就是设计算法A,从 ...

  10. 自动生成数学题型一 (框架Struts2) 题型如(a+b=c)

    1. 加减乘除 1.1 随机生成制定范围的整数 /** * 随机产生一个被限定范围的整数 * * @param num1 * 定义起始范围 num1 * @param num2 * 定义终止范围 nu ...