Java中的漏桶算法和令牌桶算法是常用的限流算法,在實(shí)現(xiàn)分布式系統(tǒng)時(shí)經(jīng)常用到。以下是對(duì)兩種算法的介紹:
漏桶算法
漏桶算法(Leaky Bucket)是一種移動(dòng)平均算法,它以固定的速度流出請(qǐng)求。當(dāng)請(qǐng)求到來時(shí),系統(tǒng)會(huì)在桶中裝入請(qǐng)求,但無論桶中請(qǐng)求的數(shù)量有多少,系統(tǒng)都以固定的速度處理請(qǐng)求。如果桶為空,系統(tǒng)將不會(huì)處理請(qǐng)求。這種方式可以平滑限制請(qǐng)求,而不是在短時(shí)間內(nèi)瞬間限制。在Java中,漏桶算法可以用以下代碼實(shí)現(xiàn):
class LeakyBucket { private long capacity; // 桶的容量 private long rate; // 桶的流出速度 private long water; // 桶中的請(qǐng)求數(shù)量 private long lastTime; // 上次流出的時(shí)間 // 構(gòu)造器 public LeakyBucket(long capacity, long rate) { this.capacity = capacity; this.rate = rate; } // 處理請(qǐng)求 public synchronized boolean handleRequest() { long now = System.currentTimeMillis(); water = Math.max(0, water - (now - lastTime) * rate / 1000); lastTime = now; if (water< capacity) { water++; return true; } else { return false; } } }
令牌桶算法
令牌桶算法(Token Bucket)是一種固定窗口算法,系統(tǒng)以固定速率向桶中放置令牌。當(dāng)請(qǐng)求到來時(shí),系統(tǒng)將從桶中獲取令牌,如果桶中沒有令牌,將不會(huì)處理請(qǐng)求。和漏桶算法一樣,令牌桶算法也可以平滑限制請(qǐng)求。另外,令牌桶算法支持時(shí)間段內(nèi)的流量控制,可以讓桶中令牌的數(shù)量隨著時(shí)間變化而變化。在Java中,令牌桶算法可以用以下代碼實(shí)現(xiàn):
class TokenBucket { private long capacity; // 桶的容量 private long rate; // 令牌放置速度 private long tokens; // 當(dāng)前桶中的令牌數(shù)量 private long lastRefillTime; // 上次放置令牌的時(shí)間 // 構(gòu)造器 public TokenBucket(long capacity, long rate) { this.capacity = capacity; this.rate = rate; } // 放置令牌 private synchronized void refill() { long now = System.currentTimeMillis(); long tokensToAdd = (now - lastRefillTime) * rate / 1000; tokens = Math.min(tokens + tokensToAdd, capacity); lastRefillTime = now; } // 處理請(qǐng)求 public synchronized boolean handleRequest() { refill(); if (tokens >0) { tokens--; return true; } else { return false; } } }