日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
生活中隨處可見的限流,在Java中又是怎么應(yīng)用的呢?

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

創(chuàng)新互聯(lián)建站主要從事網(wǎng)站設(shè)計制作、成都網(wǎng)站設(shè)計、網(wǎng)頁設(shè)計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)準格爾,10年網(wǎng)站建設(shè)經(jīng)驗,價格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):18980820575

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

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

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

  • 令牌桶算法
  • 漏桶算法

1.1 什么是漏桶算法

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

我們目前可以知道的是:

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

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

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

所以總結(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)在我有另外一個桶子,這個桶子不用來裝水,用來裝令牌:

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

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

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

  • 比如這秒我有1001個請求,我就去桶子里邊拿1001個令牌,此時可能會出現(xiàn)兩種情況:
  • 桶子里邊沒有1001個令牌,只有1000個,那沒拿到令牌的請求只能被阻塞了(等待)
  • 桶子里邊有1001個令牌,所有請求都可以執(zhí)行。

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

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

二、RateLimiter使用

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

引入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 < 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í)行三個:

三、分布式限流

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', key) or "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; // 當前秒 
  6.  String limit = "5"; // 最大限制 
  7.  List keys = new ArrayList(); 
  8.  keys.add(key); 
  9.  List args = new ArrayList(); 
  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腳本判斷當前key是否超過了最大限制limit)
  • 如果超過,則返回0(限流)
  • 如果沒超過,返回1(程序繼續(xù)執(zhí)行)

網(wǎng)頁題目:生活中隨處可見的限流,在Java中又是怎么應(yīng)用的呢?
本文地址:http://www.5511xx.com/article/cdoosij.html