一、限流基础知识介绍
创新互联建站主要从事网站设计制作、成都网站设计、网页设计、企业做网站、公司建网站等业务。立足成都服务准格尔,10年网站建设经验,价格优惠、服务专业,欢迎来电咨询建站服务:18980820575
为啥要限流,相信就不用我多说了。
在代码世界上,限流有两种比较常见的算法:
1.1 什么是漏桶算法
比如,现在我有一个桶子,绿色那块是我能装水的容量,如果超过我能装下的容量,再往桶子里边倒水,就会溢出来(限流):
我们目前可以知道的是:
OK,现在我们在桶子里挖个洞,让水可以从洞子里边流出来:
桶子的洞口的大小是固定的,所以水从洞口流出来的速率也是固定的。
所以总结下来算法所需的参数就两个:
漏桶算法有两种实现:
经过上面的分析我们就知道:
漏桶算法可以平滑网络上的突发流量(因为漏水的速率是固定的)
1.2 什么是令牌桶算法
现在我有另外一个桶子,这个桶子不用来装水,用来装令牌:
令牌会一定的速率扔进桶子里边,比如我1秒扔10个令牌进桶子:
桶子能装令牌的个数有上限的,比如我的桶子最多只能装1000个令牌。
每个请求进来,就会去桶子拿一个令牌
令牌桶算法支持网络上的突发流量
**漏桶和令牌桶的区别:**从上面的例子估计大家也能看出来了,漏桶只能以固定的速率去处理请求,而令牌桶可以以桶子最大的令牌数去处理请求
二、RateLimiter使用
RateLimiter是Guava的一个限流组件,我这边的系统就有用到这个限流组件,使用起来十分方便。
引入pom依赖:
com.google.guava guava 20.0
RateLimiter它是基于令牌桶算法的,API非常简单,看以下的Demo:
- public static void main(String[] args) {
- //线程池
- ExecutorService exec = Executors.newCachedThreadPool();
- //速率是每秒只有3个许可
- final RateLimiter rateLimiter = RateLimiter.create(3.0);
- for (int i = 0; i < 100; i++) {
- final int no = i;
- Runnable runnable = new Runnable() {
- @Override
- public void run() {
- try {
- //获取许可
- rateLimiter.acquire();
- System.out.println("Accessing: " + no + ",time:"
- + new SimpleDateFormat("yy-MM-dd HH:mm:ss").format(new Date()));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- };
- //执行线程
- exec.execute(runnable);
- }
- //退出线程池
- exec.shutdown();
- }
我们可以从结果看出,每秒只能执行三个:
三、分布式限流
RateLimiter是一个单机的限流组件,如果是分布式应用的话,该怎么做?
可以使用Redis+Lua的方式来实现,大致的lua脚本代码如下:
- local key = "rate.limit:" .. KEYS[1] --限流KEY
- local limit = tonumber(ARGV[1]) --限流大小
- local current = tonumber(redis.call('get', key) or "0")
- if current + 1 > limit then --如果超出限流大小
- return 0
- else --请求数+1,并设置1秒过期
- redis.call("INCRBY", key,"1")
- redis.call("expire", key,"1")
- return current + 1
Java代码如下:
- public static boolean accquire() throws IOException, URISyntaxException {
- Jedis jedis = new Jedis("127.0.0.1");
- File luaFile = new File(RedisLimitRateWithLUA.class.getResource("/").toURI().getPath() + "limit.lua");
- String luaScript = FileUtils.readFileToString(luaFile);
- String key = "ip:" + System.currentTimeMillis()/1000; // 当前秒
- String limit = "5"; // 最大限制
- List
keys = new ArrayList (); - keys.add(key);
- List
args = new ArrayList (); - args.add(limit);
- Long result = (Long)(jedis.eval(luaScript, keys, args)); // 执行lua脚本,传入参数
- return result == 1;
- }
解释:
当前文章:生活中随处可见的限流,在Java中又是怎么应用的呢?
本文来源:http://www.csdahua.cn/qtweb/news37/71037.html
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网