钻研一下sentinel实现的外围算法

<!-- replace here with the latest version --><dependency>    <groupId>com.alibaba.csp</groupId>    <artifactId>sentinel-core</artifactId>    <version>1.8.3</version></dependency>

官网应用阐明

List<FlowRule> rules = new ArrayList<>();FlowRule rule = new FlowRule();rule.setResource("HelloWorld");// set limit qps to 20rule.setCount(20);rule.setGrade(RuleConstant.FLOW_GRADE_QPS);rules.add(rule);FlowRuleManager.loadRules(rules);
try (Entry entry = SphU.entry("HelloWorld")) {    // Your business logic here.    System.out.println("hello world");} catch (BlockException e) {    // Handle rejected request.    e.printStackTrace();}// try-with-resources auto exit

为了看一下外围实现环节,为了更直观的进行了解,这里把一秒分成两个窗口,即每个窗口slidingWindowSize为500, 并且进行了简洁的从新编写

    private static long slidingWindowSize = 500L;    private AtomicReferenceArray<Item> array = new AtomicReferenceArray<Item>(2);    private ReentrantLock lock = new ReentrantLock();    private long permitsPerSecond; //设定每秒容许的qps

入口办法

    public boolean entry() {        try {            long currentTimeMillis = System.currentTimeMillis();            int index = findSlidingWindowIndex(currentTimeMillis);            long slidingWindowStart = findSlidingWindowStart(currentTimeMillis);            Item item = currentItem(index, slidingWindowStart);            if (item == null) {                return true;            }            if (accumulatedPassQps(1 - index, item) > permitsPerSecond) {                return false;            }            item.passIncrement();            return true;        } catch (Exception ex) {            return true;        }    }

累计曾经通过的qps

    private long accumulatedPassQps(int index, Item item) {        Item other = array.get(index);        if (other == null                || (Math.abs(other.getSlidingWindowStart() - item.getSlidingWindowStart()) > slidingWindowSize)) {            return item.passValue();        }        return other.passValue() + item.passValue();    }

以后是哪个工夫窗口

    private Item currentItem(int index, long slidingWindowStart) {        while (true) {            Item previous = array.get(index);            if (previous == null) {                Item item = new Item(slidingWindowStart);                if (array.compareAndSet(index, null, item)) {                    return item;                } else {                    Thread.yield();                }            } else if (slidingWindowStart == previous.getSlidingWindowStart()) {                return previous;            } else if (slidingWindowStart > previous.getSlidingWindowStart()) {                if (lock.tryLock()) {                    try {                        return previous.reset(slidingWindowStart);                    } finally {                        lock.unlock();                    }                } else {                    Thread.yield();                }            } else {                return null;            }        }    }
    private long findSlidingWindowStart(long timeMillis) {        return timeMillis - timeMillis % slidingWindowSize;    }    private int findSlidingWindowIndex(long timeMillis) {        return (int) ((timeMillis / slidingWindowSize) % 2);    }

Item封装的内容

    private long slidingWindowStart;    private LongAdder accu;
    public Item reset(long slidingWindowStart) {        this.slidingWindowStart = slidingWindowStart;        accu.reset();        return this;    }    public long passValue() {        return accu.sum();    }    public void passIncrement() {        accu.increment();    }    public long getSlidingWindowStart() {        return slidingWindowStart;    }