自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

生活中隨處可見的限流,在Java中又是怎么應(yīng)用的呢?

開發(fā) 后端
回到代碼世界上也是一樣的,服務(wù)器能處理的請求數(shù)有限,如果請求量特別大,我們需要做限流(要么就讓請求等待,要么就把請求給扔了)

 [[277344]]

一、限流基礎(chǔ)知識介紹

為啥要限流,相信就不用我多說了。

  • 比如,我周末去飯店吃飯,但是人太多了,我只能去前臺拿個號,等號碼到我的時候才能進飯店吃飯。如果飯店沒有限流怎么辦?一到飯點,人都往里沖,而飯店又處理不了這么多人流,很容易就出事故(飯店塞滿了人,無路可走。飯店的工作人員崩潰了,處理不過來)
  • 回到代碼世界上也是一樣的,服務(wù)器能處理的請求數(shù)有限,如果請求量特別大,我們需要做限流(要么就讓請求等待,要么就把請求給扔了)

 

在代碼世界上,限流有兩種比較常見的算法:

  • 令牌桶算法
  • 漏桶算法

1.1 什么是漏桶算法

比如,現(xiàn)在我有一個桶子,綠色那塊是我能裝水的容量,如果超過我能裝下的容量,再往桶子里邊倒水,就會溢出來(限流):

生活中隨處可見的限流,在Java中又是怎么應(yīng)用的呢?

我們目前可以知道的是:

  • 桶子的容量是固定的(是圖上綠色那塊)
  • 超出了桶子的容量就會溢出(要么等待,要么直接丟棄)

OK,現(xiàn)在我們在桶子里挖個洞,讓水可以從洞子里邊流出來:

生活中隨處可見的限流,在Java中又是怎么應(yīng)用的呢?

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

所以總結(jié)下來算法所需的參數(shù)就兩個:

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

漏桶算法有兩種實現(xiàn):

  • 不允許突發(fā)流量的情況:如果進水的速率大于出水的速率,直接舍棄掉多余的水。比如,我的桶子容量能裝100L,但我的桶子出水速率是10L/s。此時,如果現(xiàn)在有100L/s的水進來,我只讓10L的水進到桶子,其余的都限流。(限定了請求的速度)
  • 允許一定的突發(fā)流量情況:我的桶子能裝100L,如果現(xiàn)在我的桶子是空的,那么這100L的水都能進我的桶子。我以10L/s的速率將這些水流出,如果還有100L的水進來,只能限流了。

經(jīng)過上面的分析我們就知道:

漏桶算法可以平滑網(wǎng)絡(luò)上的突發(fā)流量(因為漏水的速率是固定的)

1.2 什么是令牌桶算法

現(xiàn)在我有另外一個桶子,這個桶子不用來裝水,用來裝令牌:

生活中隨處可見的限流,在Java中又是怎么應(yīng)用的呢?

令牌會一定的速率扔進桶子里邊,比如我1秒扔10個令牌進桶子:

生活中隨處可見的限流,在Java中又是怎么應(yīng)用的呢?

桶子能裝令牌的個數(shù)有上限的,比如我的桶子最多只能裝1000個令牌。

每個請求進來,就會去桶子拿一個令牌

  • 比如這秒我有1001個請求,我就去桶子里邊拿1001個令牌,此時可能會出現(xiàn)兩種情況:
  • 桶子里邊沒有1001個令牌,只有1000個,那沒拿到令牌的請求只能被阻塞了(等待)
  • 桶子里邊有1001個令牌,所有請求都可以執(zhí)行。
生活中隨處可見的限流,在Java中又是怎么應(yīng)用的呢?

令牌桶算法支持網(wǎng)絡(luò)上的突發(fā)流量

**漏桶和令牌桶的區(qū)別:**從上面的例子估計大家也能看出來了,漏桶只能以固定的速率去處理請求,而令牌桶可以以桶子最大的令牌數(shù)去處理請求

二、RateLimiter使用

RateLimiter是Guava的一個限流組件,我這邊的系統(tǒng)就有用到這個限流組件,使用起來十分方便。

引入pom依賴:

  1. <dependency> 
  2.  <groupId>com.google.guava</groupId> 
  3.  <artifactId>guava</artifactId> 
  4.  <version>20.0</version> 
  5. </dependency> 

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 < 100; 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.  //執(zhí)行線程 
  22.  exec.execute(runnable); 
  23.  } 
  24.  //退出線程池 
  25.  exec.shutdown(); 
  26.  } 

我們可以從結(jié)果看出,每秒只能執(zhí)行三個:

生活中隨處可見的限流,在Java中又是怎么應(yīng)用的呢?

三、分布式限流

RateLimiter是一個單機的限流組件,如果是分布式應(yīng)用的話,該怎么做?

可以使用Redis+Lua的方式來實現(xiàn),大致的lua腳本代碼如下:

  1. local key = "rate.limit:" .. KEYS[1] --限流KEY 
  2. local limit = tonumber(ARGV[1]) --限流大小 
  3. local current = tonumber(redis.call('get'keyor "0"
  4. if current + 1 > limit then --如果超出限流大小 
  5.  return 0 
  6. else --請求數(shù)+1,并設(shè)置1秒過期 
  7.  redis.call("INCRBY"key,"1"
  8.  redis.call("expire"key,"1"
  9.  return current + 1 

Java代碼如下:

  1. public static boolean accquire() throws IOException, URISyntaxException { 
  2.  Jedis jedis = new Jedis("127.0.0.1"); 
  3.  File luaFile = new File(RedisLimitRateWithLUA.class.getResource("/").toURI().getPath() + "limit.lua"); 
  4.  String luaScript = FileUtils.readFileToString(luaFile); 
  5.  String key = "ip:" + System.currentTimeMillis()/1000; // 當(dāng)前秒 
  6.  String limit = "5"; // 最大限制 
  7.  List<String> keys = new ArrayList<String>(); 
  8.  keys.add(key); 
  9.  List<String> args = new ArrayList<String>(); 
  10.  args.add(limit); 
  11.  Long result = (Long)(jedis.eval(luaScript, keys, args)); // 執(zhí)行l(wèi)ua腳本,傳入?yún)?shù) 
  12.  return result == 1; 

解釋:

  • Java代碼傳入key和最大的限制limit參數(shù)進lua腳本
  • 執(zhí)行l(wèi)ua腳本(lua腳本判斷當(dāng)前key是否超過了最大限制limit)
  • 如果超過,則返回0(限流)
  • 如果沒超過,返回1(程序繼續(xù)執(zhí)行)

 

責(zé)任編輯:武曉燕 來源: 今日頭條
相關(guān)推薦

2011-05-12 13:14:07

MacBook谷歌蘋果

2021-01-04 13:00:41

物聯(lián)網(wǎng)醫(yī)療資產(chǎn)管理

2013-03-21 17:44:03

2021-04-13 16:07:16

比特幣加密貨幣ATM

2022-05-10 11:30:23

人工智能機器學(xué)習(xí)

2020-04-14 15:58:15

物聯(lián)網(wǎng)安全農(nóng)業(yè)

2023-06-08 09:27:28

2022-02-28 08:17:24

重載函數(shù)JS前端

2020-05-26 14:45:09

生物識別數(shù)據(jù)安全人工智能

2023-05-05 08:18:38

Linuxsource命令

2018-01-04 14:35:54

大數(shù)據(jù)安防智慧城市

2013-01-21 10:20:22

以太網(wǎng)GSM數(shù)據(jù)傳輸

2021-06-29 12:21:59

人工智能

2021-02-03 11:50:05

人工智能人臉識別

2020-04-10 08:44:15

5G基站天線

2020-12-31 08:30:00

推薦系統(tǒng)MatRec計算機

2017-12-05 16:26:36

爬蟲大數(shù)據(jù)共享單車

2009-06-11 13:52:25

協(xié)同軟件Java

2021-12-14 10:24:44

可見性網(wǎng)絡(luò)安全零信任

2019-11-14 09:32:16

程序員MySQLRedis
點贊
收藏

51CTO技術(shù)棧公眾號