设为首页 - 加入收藏 渭南站长网 (http://www.0913zz.com)- 国内知名站长资讯网站,提供最新最全的站长资讯,创业经验,网站建设等!
热搜: 平台 2015 演示
当前位置: 首页 > 运营中心 > 建站资源 > 优化 > 正文

生活中随处可见的限流,在Java中又是怎么应用的呢?

发布时间:2019-09-21 23:09 所属栏目:[优化] 来源:Java之高级架构
导读:一、限流基础知识介绍 为啥要限流,相信就不用我多说了。 比如,我周末去饭店吃饭,但是人太多了,我只能去前台拿个号,等号码到我的时候才能进饭店吃饭。如果饭店没有限流怎么办?一到饭点,人都往里冲,而饭店又处理不了这么多人流,很容易就出事故(饭店

?生活中随处可见的限流,在Java中又是怎么应用的呢?

一、限流基础知识介绍

为啥要限流,相信就不用我多说了。

  • 比如,我周末去饭店吃饭,但是人太多了,我只能去前台拿个号,等号码到我的时候才能进饭店吃饭。如果饭店没有限流怎么办?一到饭点,人都往里冲,而饭店又处理不了这么多人流,很容易就出事故(饭店塞满了人,无路可走。饭店的工作人员崩溃了,处理不过来)
  • 回到代码世界上也是一样的,服务器能处理的请求数有限,如果请求量特别大,我们需要做限流(要么就让请求等待,要么就把请求给扔了)

在代码世界上,限流有两种比较常见的算法:

  • 令牌桶算法
  • 漏桶算法

1.1 什么是漏桶算法

比如,现在我有一个桶子,绿色那块是我能装水的容量,如果超过我能装下的容量,再往桶子里边倒水,就会溢出来(限流):

生活中随处可见的限流,在Java中又是怎么应用的呢?

我们目前可以知道的是:

  • 桶子的容量是固定的(是图上绿色那块)
  • 超出了桶子的容量就会溢出(要么等待,要么直接丢弃)

OK,现在我们在桶子里挖个洞,让水可以从洞子里边流出来:

生活中随处可见的限流,在Java中又是怎么应用的呢?

桶子的洞口的大小是固定的,所以水从洞口流出来的速率也是固定的。

所以总结下来算法所需的参数就两个:

  • 桶子的容量
  • 漏水的速率

漏桶算法有两种实现:

  • 不允许突发流量的情况:如果进水的速率大于出水的速率,直接舍弃掉多余的水。比如,我的桶子容量能装100L,但我的桶子出水速率是10L/s。此时,如果现在有100L/s的水进来,我只让10L的水进到桶子,其余的都限流。(限定了请求的速度)
  • 允许一定的突发流量情况:我的桶子能装100L,如果现在我的桶子是空的,那么这100L的水都能进我的桶子。我以10L/s的速率将这些水流出,如果还有100L的水进来,只能限流了。

经过上面的分析我们就知道:

漏桶算法可以平滑网络上的突发流量(因为漏水的速率是固定的)

1.2 什么是令牌桶算法

现在我有另外一个桶子,这个桶子不用来装水,用来装令牌:

生活中随处可见的限流,在Java中又是怎么应用的呢?

令牌会一定的速率扔进桶子里边,比如我1秒扔10个令牌进桶子:

生活中随处可见的限流,在Java中又是怎么应用的呢?

桶子能装令牌的个数有上限的,比如我的桶子最多只能装1000个令牌。

每个请求进来,就会去桶子拿一个令牌

  • 比如这秒我有1001个请求,我就去桶子里边拿1001个令牌,此时可能会出现两种情况:
  • 桶子里边没有1001个令牌,只有1000个,那没拿到令牌的请求只能被阻塞了(等待)
  • 桶子里边有1001个令牌,所有请求都可以执行。
生活中随处可见的限流,在Java中又是怎么应用的呢?

令牌桶算法支持网络上的突发流量

**漏桶和令牌桶的区别:**从上面的例子估计大家也能看出来了,漏桶只能以固定的速率去处理请求,而令牌桶可以以桶子最大的令牌数去处理请求

二、RateLimiter使用

RateLimiter是Guava的一个限流组件,我这边的系统就有用到这个限流组件,使用起来十分方便。

引入pom依赖:

  1. ?
  2. ?com.google.guava?
  3. ?guava?
  4. ?20.0?
  5. ?

RateLimiter它是基于令牌桶算法的,API非常简单,看以下的Demo:

  1. public?static?void?main(String[]?args)?{?
  2. ?//线程池?
  3. ?ExecutorService?exec?=?Executors.newCachedThreadPool();?
  4. ?//速率是每秒只有3个许可?
  5. ?final?RateLimiter?rateLimiter?=?RateLimiter.create(3.0);?
  6. ?for?(int?i?=?0;?i?
  7. ?final?int?no?=?i;?
  8. ?Runnable?runnable?=?new?Runnable()?{?
  9. ?@Override?
  10. ?public?void?run()?{?
  11. ?try?{?
  12. ?//获取许可?
  13. ?rateLimiter.acquire();?
  14. ?System.out.println("Accessing:?"?+?no?+?",time:"?
  15. ?+?new?SimpleDateFormat("yy-MM-dd?HH:mm:ss").format(new?Date()));?
  16. ?}?catch?(Exception?e)?{?
  17. ?e.printStackTrace();?
  18. ?}?
  19. ?}?
  20. ?};?
  21. ?//执行线程?
  22. ?exec.execute(runnable);?
  23. ?}?
  24. ?//退出线程池?
  25. ?exec.shutdown();?
  26. ?}?

【免责声明】本站内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。

网友评论
推荐文章