日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

Java高并发系统的限流策略

發布時間:2024/4/13 windows 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java高并发系统的限流策略 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

限流算法

令牌桶(Token Bucket)、漏桶(leaky bucket)和計數器算法是最常用的三種限流的算法。

計數器限流算法也是比較常用的,主要用來限制總并發數,比如數據庫連接池大小、線程池大小、程序訪問并發數等都是使用計數器算法。也是最簡單粗暴的算法。

使用計數器限流示例1:

public class CountRateLimiterDemo { 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 CountRateLimiterDemo { private static Semaphore semphore = new Semaphore(50); 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優點:如果是瞬時的高并發,可以使請求在阻塞隊列中排隊,而不是馬上拒絕請求,從而達到一個流量削峰的目的。

使用guava的RateLimiter限流示例3

Guava中開源工具類RateLimiter是基于令牌桶算法的實現類,可以簡單的實現限流的工作,并根據系統實際情況調整生成token速率。RateLimiter 對簡單的令牌桶算法做了一些工程上的優化,具體的實現是 SmoothBursty。需要注意的是,RateLimiter 的另一個實現 SmoothWarmingUp,就不是令牌桶了,而是漏桶算法。也許是出于簡單起見,RateLimiter 中的時間窗口能且僅能為 1s,如果想搞其他時間單位的限流,只能另外造輪子。

RateLimiter 有一個有趣的特性是「前人挖坑后人跳」,也就是說 RateLimiter 允許某次請求拿走超出剩余令牌數的令牌,但是下一次請求將為此付出代價,一直等到令牌虧空補上,并且桶中有足夠本次請求使用的令牌為止。這里面就涉及到一個權衡,是讓前一次請求干等到令牌夠用才走掉呢,還是讓它先走掉后面的請求等一等呢?Guava 的設計者選擇的是后者,先把眼前的活干了,后面的事后面再說。

RateLimiter rateLimiter = RateLimiter.create(2);

System.out.println(rateLimiter.acquire(5));

System.out.println(rateLimiter.acquire(2));

System.out.println(rateLimiter.acquire(1));

輸出

0.0

2.496889

0.992149

?

可以看出,令牌桶每秒只能產生2個令牌,我們可以第一次取出5個,但是第二個再去取令牌的時候,需要等2.5s,也就是第一次令牌取完后,需要等2.5s才能取到令牌。同樣的,第三次取1個令牌的時候,也需要等待第二次的1s的時間。也就是,取的速率可以超過令牌產生的速率,但是下一次再次去取的時候,需要阻塞等待。

當然也可以使用tryAcquire來非阻塞的獲取,可以實時返回結果。另外tryAcquire也可以傳入參數,也就是等待的時間,超時直接返回false。這點等同于常見的lock,tryLock。

?

總結

以上是生活随笔為你收集整理的Java高并发系统的限流策略的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。