1. 程式人生 > >從修身齊家治國平天下談分散式系統中的限流與熔斷

從修身齊家治國平天下談分散式系統中的限流與熔斷

“古之慾明明德於天下者,先治其國;欲治其國者,先齊其家;欲齊其家者,先修其身;欲修其身者,先正其心;欲正其心者,先誠其意;欲誠其意者,先致其知,致知在格物。物格而後知至,知至而後意誠,意誠而後心正,心正而後身修,身修而後家齊,家齊而後國治,國治而後天下平。”--《禮記·大學》

在應對秒殺、大促、雙 11、618 等高效能壓力的場景時,限流已經成為了標配技術解決方案,為保證系統的平穩執行起到了關鍵性的作用。不管應用場景是哪種,限流無非就是針對超過預期的流量,通過預先設定的限流規則選擇性的對某些請求進行限流“熔斷”。

根據修身、齊家、治國平天下的理念,限流與熔斷要先從小點著手,即先對單機進行限流與熔斷,然後對微服務小叢集做限流與熔斷,最後是對整個流程的服務叢集做限流與熔斷。

1. 限流

1.1 單機限流(修身)

  修身

a>>限制併發量

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoreTest {
 private static final int THREAD_COUNT = 30;
 private static ExecutorService threadPool = Executors
 .newFixedThreadPool(THREAD_COUNT);
 private static Semaphore s = new Semaphore(10);
 public static void main(String[] args) {
 for (int i = 0; i < THREAD_COUNT; i++) {
 threadPool.execute(new Runnable() {
 @Override
 public void run() {
 try {
 s.acquire();
 System.out.println(Thread.currentThread().getName());
 Thread.sleep(5000);
 System.out.println("--------------");
 s.release();
 } catch (InterruptedException e) {
 }
 }
 });
 }
 threadPool.shutdown();
 }
}

 

b>>計數器,以CountDownLatch為例

import java.util.concurrent.CountDownLatch;
public class CountDownLatchTest2 {
 public static void main(String[] args) {
 // 建立計數器,初始化為2
 final CountDownLatch latch = new CountDownLatch(2);
 new Thread(() -> {
 try {
 System.out.println("子執行緒"+Thread.currentThread().getName()+"正在執行");
 Thread.sleep(3000);
 System.out.println("子執行緒"+Thread.currentThread().getName()+"執行完畢");
 latch.countDown();// 減一
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 }).start();
 new Thread(() -> {
 try {
 System.out.println("子執行緒"+Thread.currentThread().getName()+"正在執行");
 Thread.sleep(3000);
 System.out.println("子執行緒"+Thread.currentThread().getName()+"執行完畢");
 latch.countDown();
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 }).start();
 try {
 System.out.println("等待2個子執行緒執行完畢...");
 // 阻塞
 latch.await();
 System.out.println("2個子執行緒已經執行完畢");
 System.out.println("繼續執行主執行緒");
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 }
}

c>>guava RateLimiter

public void test()
{
 /**
 * 建立一個限流器,設定每秒放置的令牌數:2個。速率是每秒可以2個的訊息。
 * 返回的RateLimiter物件可以保證1秒內不會給超過2個令牌,並且是固定速率的放置。達到平滑輸出的效果
 */
 RateLimiter r = RateLimiter.create(2);
 while (true)
 {
 /**
 * acquire()獲取一個令牌,並且返回這個獲取這個令牌所需要的時間。如果桶裡沒有令牌則等待,直到有令牌。
 * acquire(N)可以獲取多個令牌。
 */
 System.out.println(r.acquire());
 }
}

 

1.2 分散式限流(齊家)

                齊家

a>> nginx

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s;
server { 
 location / { 
 limit_req zone=mylimit;
 }
}

 

b>>api-gateway+redis限流

https://github.com/wangzheng0822/ratelimiter4j

1.3 大流程限流(治國平天下)

可以從防火牆,cdn,路由器,api閘道器等做限流

                              治國平天下

2. 熔斷對比

熔斷處理邏輯類似,可以利用一些現成的框架,如Sentinel、Hystrix、resilience4j等。

功能對比

熔斷對比

參考文獻:

【1】https://mp.weixin.qq.com/s?__biz=MjM5MDE0Mjc4MA==&mid=2651008444&idx=1&sn=a579c3ceb143ea30930bd4c6d4a8d7e2&chksm=bdbed5ef8ac95cf93e71c5393f08e3b97a7e19e8232ce3872231f2cae74f7a19ab15501aeb44&scene=27#wechat_redirect

【2】https://mp.weixin.qq.com/s?__biz=MzIwMzY1OTU1NQ==&mid=2247484306&idx=1&sn=b6c1b7b9d7c57bbb9f82ec451bcda867&chksm=96cd43dea1bacac8a24cde429146f69dba8bb15c5c9c3fe9adfe858d9a4349cc127fbfa84a8c&scene=27#wechat_redirect

【3】https://github.com/alibaba/Sentinel/wiki/Guideline:-%E4%BB%8E-Hystrix-%E8%BF%81%E7%A7%BB%E5%88%B0-Sent