1. 程式人生 > >Sentinel併發限流不精確-之責任鏈

Sentinel併發限流不精確-之責任鏈

​ 在之前調研Sentinel的過程中,為了準備分享內容,自己就簡單的寫了一些測試程式碼,不過在測試中遇到了一些問題,其中有一個問題就是Sentinel流控在併發情況下限流並不精確,當時我還在想,這個我在做分享的時候該怎麼來自圓其說呢,所以覺得比較有意思,在這裡做一個記錄。同時在排查這個問題的過程中,為了說清楚問題原因,我覺得有必要理一下它的責任鏈,所以副標題就是Sentinel的責任鏈。 *** # 一、問題起源 ​ 在這裡我直接上我的測試程式碼,我的本意是要起10個執行緒同時去請求這個資源,每個執行緒輪詢10次。同時,對於這個資源我設定了限流規則為QPS=1。這也就意味著我這10個執行緒共100個請求,正確的結果應該是成功1個,阻塞99個。 ~~~java import com.alibaba.csp.sentinel.Entry; import com.alibaba.csp.sentinel.SphU; import com.alibaba.csp.sentinel.slots.block.BlockException; import com.alibaba.csp.sentinel.slots.block.RuleConstant; import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; /** * 流量控制演示 */ public class FlowQpsDemo_Bug { private static final String SOURCE_KEY = "CESHI_KEY"; private static AtomicInteger pass = new AtomicInteger(); private static AtomicInteger block = new AtomicInteger(); private static AtomicInteger total = new AtomicInteger(); public static void main(String[] args) throws InterruptedException { initFlowQpsRule(); CountDownLatch start = new CountDownLatch(1); CountDownLatch end = new CountDownLatch(10); for (int i = 0;i < 10;i++) { new Thread(new Runnable() { @Override public void run() { try { start.await(); } catch (InterruptedException e) { } for (int i = 0;i < 10;i++) { fun(); } end.countDown(); } }).start(); } start.countDown(); end.await(); System.out.println("total=" + total.get() + " pass=" + pass.get() + " block=" + block.get()); } public static void fun() { Entry entry = null; try { entry = SphU.entry(SOURCE_KEY); // todo 業務邏輯 pass.incrementAndGet(); } catch (BlockException e1) { // todo 流控處理 block.incrementAndGet(); } finally { total.incrementAndGet(); if (entry != null) { entry.exit(); } } } private static void initFlowQpsRule() {