java 限流策略
概要
在大數據量高并發訪問時,經常會出現服務或接口面對暴漲的請求而不可用的情況,甚至引發連鎖反映導致整個系統崩潰。此時你需要使用的技術手段之一就是限流,當請求達到一定的并發數或速率,就進行等待、排隊、降級、拒絕服務等。在限流時,常見的兩種算法是漏桶和令牌桶算法算法。
限流算法
令牌桶(Token Bucket)、漏桶(leaky bucket)和計數器算法是最常用的三種限流的算法。
1. 令牌桶算法
令牌桶算法的原理是系統會以一個恒定的速度往桶里放入令牌,而如果請求需要被處理,則需要先從桶里獲取一個令牌,當桶里沒有令牌可取時,則拒絕服務。 當桶滿時,新添加的令牌被丟棄或拒絕。
令牌桶算法示例
public class RateLimiterDemo {private static RateLimiter limiter = RateLimiter.create(5);public static void exec() {limiter.acquire(1);try {// 處理核心邏輯TimeUnit.SECONDS.sleep(1);System.out.println("--" + System.currentTimeMillis() / 1000);} catch (InterruptedException e) {e.printStackTrace();}} }Guava RateLimiter 提供了令牌桶算法可用于平滑突發限流策略。
該示例為每秒中產生5個令牌,每200毫秒會產生一個令牌。
limiter.acquire() 表示消費一個令牌。當桶中有足夠的令牌時,則直接返回0,否則阻塞,直到有可用的令牌數才返回,返回的值為阻塞的時間。
2. 漏桶算法
它的主要目的是控制數據注入到網絡的速率,平滑網絡上的突發流量,數據可以以任意速度流入到漏桶中。漏桶算法提供了一種機制,通過它,突發流量可以被整形以便為網絡提供一個穩定的流量。 漏桶可以看作是一個帶有常量服務時間的單服務器隊列,如果漏桶為空,則不需要流出水滴,如果漏桶(包緩存)溢出,那么水滴會被溢出丟棄。
3. 計數器限流算法
計數器限流算法也是比較常用的,主要用來限制總并發數,比如數據庫連接池大小、線程池大小、程序訪問并發數等都是使用計數器算法。
使用計數器限流示例1
public class CountRateLimiterDemo1 {private static AtomicInteger count = new AtomicInteger(0);public static void exec() {if (count.get() >= 5) {System.out.println("請求用戶過多,請稍后在試!"+System.currentTimeMillis()/1000);} else {count.incrementAndGet();try {//處理核心邏輯TimeUnit.SECONDS.sleep(1);System.out.println("--"+System.currentTimeMillis()/1000);} catch (InterruptedException e) {e.printStackTrace();} finally {count.decrementAndGet();}}} }使用AomicInteger來進行統計當前正在并發執行的次數,如果超過域值就簡單粗暴的直接響應給用戶,說明系統繁忙,請稍后再試或其它跟業務相關的信息。
弊端:使用 AomicInteger 簡單粗暴超過域值就拒絕請求,可能只是瞬時的請求量高,也會拒絕請求。
使用計數器限流示例2
public class CountRateLimiterDemo2 {private static Semaphore semphore = new Semaphore(5);public static void exec() {if(semphore.getQueueLength()>100){System.out.println("當前等待排隊的任務數大于100,請稍候再試...");}try {semphore.acquire();// 處理核心邏輯TimeUnit.SECONDS.sleep(1);System.out.println("--" + System.currentTimeMillis() / 1000);} catch (InterruptedException e) {e.printStackTrace();} finally {semphore.release();}} }使用Semaphore信號量來控制并發執行的次數,如果超過域值信號量,則進入阻塞隊列中排隊等待獲取信號量進行執行。如果阻塞隊列中排隊的請求過多超出系統處理能力,則可以在拒絕請求。
相對Atomic優點:如果是瞬時的高并發,可以使請求在阻塞隊列中排隊,而不是馬上拒絕請求,從而達到一個流量削峰的目的。
想了解更多精彩內容請關注我的公眾號
本人簡書blog地址:http://www.jianshu.com/u/1f0067e24ff8????
點擊這里快速進入簡書
GIT地址:http://git.oschina.net/brucekankan/
點擊這里快速進入GIT
總結
- 上一篇: Junit 测试之 Spring Te
- 下一篇: 前后端分离 跨域问题解决