限流系列
開源元件 rate-limit: 限流
高可用之限流-01-入門介紹
高可用之限流-02-如何設計限流框架
高可用之限流-03-Semaphore 訊號量做限流
高可用之限流-04-fixed window 固定視窗
高可用之限流-05-slide window 滑動視窗
高可用之限流-06-slide window 滑動視窗 sentinel 原始碼
高可用之限流-07-token bucket 令牌桶演算法
高可用之限流 08-leaky bucket漏桶演算法
高可用之限流 09-guava RateLimiter 入門使用簡介 & 原始碼分析
主流的限流方式
目前主要有以下幾種限流方式:
-
訊號量
-
計數器
-
滑動視窗
-
漏桶演算法
-
令牌桶演算法
-
分散式限流
訊號量
訊號量實際上就是限制系統的併發量,來達到限流的目的。
常見的用法是:建立Semaphore,指定permit的數量。
在方法開始時,呼叫 Semaphore.acquire() 或者 Semaphore.tryAcquire() 來獲取permit,並在方法返回前,呼叫Semaphore.release()來返還permit。
核心程式碼實現
public class LimitSemaphore extends LimitAdaptor {
/**
* 日誌
*
* @since 0.0.5
*/
private static final Log LOG = LogFactory.getLog(LimitSemaphore.class);
/**
* 訊號量
*
* @since 0.0.5
*/
private final Semaphore semaphore;
/**
* 構造器
*
* @param context 上下文
* @since 0.0.5
*/
public LimitSemaphore(final ILimitContext context) {
this.semaphore = new Semaphore(context.count());
}
@Override
public synchronized void acquire() {
try {
LOG.debug("[Limit] start acquire");
this.semaphore.acquire(1);
LOG.debug("[Limit] end acquire");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
LOG.error("[Limit] semaphore meet ex: ", e);
}
}
@Override
public void release() {
LOG.debug("[Limit] start release");
this.semaphore.release(1);
LOG.debug("[Limit] end release");
}
}
測試
我們限定每次只有一個執行緒可以執行核心方法,如下:
public class LimitSemaphoreTest {
private static final Log LOG = LogFactory.getLog(LimitSemaphoreTest.class);
private static final ILimit LIMIT = LimitBs.newInstance(LimitSemaphore.class)
.count(1)
.build();
static class LimitRunnable implements Runnable {
@Override
public void run() {
for(int i = 0; i < 2; i++) {
try {
LIMIT.acquire();
LOG.info("{}-{}", Thread.currentThread().getName(), i);
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
LIMIT.release();
}
}
}
}
public static void main(String[] args) {
new Thread(new LimitRunnable()).start();
new Thread(new LimitRunnable()).start();
}
}
- 日誌輸出
13:35:37.501 [Thread-1] INFO com.github.houbb.rate.limit.test.semaphore.LimitSemaphoreTest - Thread-1-0
13:35:38.501 [Thread-2] INFO com.github.houbb.rate.limit.test.semaphore.LimitSemaphoreTest - Thread-2-0
13:35:39.502 [Thread-1] INFO com.github.houbb.rate.limit.test.semaphore.LimitSemaphoreTest - Thread-1-1
13:35:40.503 [Thread-2] INFO com.github.houbb.rate.limit.test.semaphore.LimitSemaphoreTest - Thread-2-1
可以看到每次只有一個執行緒可以執行方法。
小結
這種方法最為簡單,但是存在很多問題。
併入併發量問題,比如控制的力度不夠靈活細緻等。
後續我們來看下其他的實現方式。
參考資料
限流技術總結