Sentinel指南:初識(shí)Sentinel

文章目錄

  1. 概述
  2. 如何使用
  3. 流量控制
  4. 熔斷降級(jí)
  5. 控制臺(tái)
  6. 總結(jié)

Sentinel是阿里中間件團(tuán)隊(duì)開源的涩赢,面向分布式服務(wù)架構(gòu)的輕量級(jí)高可用流量控制組件。與Hystrix庫相比,它提供了更豐富的功能,以及更直觀的實(shí)現(xiàn)煌茬。本文主參考Sentinel官方提供的示例,讓更多的朋友體對(duì)sentinel有一個(gè)初步的認(rèn)識(shí)彻桃。在后續(xù)的文章中會(huì)講述它的實(shí)現(xiàn)原理細(xì)節(jié)坛善。

1. 概述

Sentinel主要提供了流量控制、服務(wù)降級(jí)邻眷、系統(tǒng)負(fù)載保護(hù)眠屎、實(shí)時(shí)數(shù)據(jù)監(jiān)控等功能。

先從流量控制說起肆饶,什么是流量控制改衩?顧名思義,和字面名字的含義差不多驯镊,只不過這里的流量一般指的是對(duì)RPC服務(wù)調(diào)用的流量葫督。那么為什么要對(duì)它進(jìn)行控制呢?一個(gè)原因是一般我們的一臺(tái)服務(wù)器可能對(duì)提供過個(gè)RPC服務(wù)板惑,如果一個(gè)服務(wù)占用過多的資源橄镜,那么其他的服務(wù)可能不能正常的提供服務(wù)了。還有過多的請(qǐng)求會(huì)降低服務(wù)質(zhì)量等原因冯乘。

Sentinel提供了兩種流量控制方式洽胶,一是QPS,二是服務(wù)的線程數(shù)裆馒。
關(guān)于服務(wù)熔斷降級(jí)姊氓,老生常談的話題丐怯。Sentinel提供了兩種降級(jí)策略,一是RT(run time),二是異常比例翔横。后面結(jié)合Demo解釋

2. 如何使用读跷?

Sentinel資源保護(hù)(流量控制和熔斷降級(jí)),這里的資源可以使RPC服務(wù)禾唁、方法等舔亭。主要分為兩個(gè)步驟:

  1. 定義規(guī)則,就是定義某個(gè)資源保護(hù)的規(guī)則蟀俊,比如限流策略、降級(jí)策略等订雾。
  2. 訪問資源肢预,說白了就是給資源起一個(gè)名字,為了區(qū)分其他資源

其實(shí)官網(wǎng)上把第二步稱為資源定義洼哎,但是個(gè)人認(rèn)為把它成為資源訪問更為合適烫映,因?yàn)镵EY代表了某個(gè)資源,但是具體代表了哪個(gè)資源是通過訪問某資源時(shí)才能確定的噩峦。

3. 流量控制

下面定義規(guī)則锭沟,Sentinel 支持三種規(guī)則:流量控制規(guī)則、熔斷降級(jí)規(guī)則以及系統(tǒng)保護(hù)規(guī)則识补。這里先試試流量控制規(guī)則族淮。

private static void initFlowQpsRule() {
    // 規(guī)則對(duì)應(yīng)的類為FlowRule,用List保存凭涂,可以有多個(gè)規(guī)則
    List<FlowRule> rules = new ArrayList<FlowRule>();
    FlowRule rule1 = new FlowRule();
    rule1.setResource(KEY);
    // QPS為20
    rule1.setCount(20);
    //限流的類型
    rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
    rule1.setControlBehavior(CONTROL_BEHAVIOR_DEFAULT);
    rules.add(rule1);
    FlowRuleManager.loadRules(rules);
}

流量控制規(guī)則對(duì)應(yīng)的類為FlowRule

  • setResource(KEY)方法是設(shè)置資源名祝辣,也就是限流規(guī)則的作用對(duì)象,更通俗的講:本條規(guī)則對(duì)哪個(gè)資源生效切油。
  • count是限流閾值蝙斜,當(dāng)我們定義的是流量控制規(guī)則是根據(jù)QPS進(jìn)行限流時(shí),它表示QPS的閾值澎胡,當(dāng)然如果是根據(jù)線程數(shù)限流孕荠,它表示線程數(shù)。
  • grade表示限流閾值類型攻谁,是按照 QPS 還是線程數(shù)默認(rèn)根據(jù) QPS稚伍。
  • controlBehavior表示發(fā)生攔截后是直接拒絕,還是排隊(duì)等待巢株,還是慢啟動(dòng)模式槐瑞,默認(rèn)是直接拒絕,如果設(shè)置為排隊(duì)等待則還需要設(shè)置maxQueueingTimeMs(最大排隊(duì)時(shí)間)阁苞。

最后 FlowRuleManager.loadRules(rules)是將rules生效困檩§舸欤總體的來說Sentinel的API比較直觀易懂,我們繼續(xù)往下悼沿,開始訪問我們定義的資源等舔。

下面結(jié)合一個(gè)例子對(duì)Sentinel有進(jìn)一步的認(rèn)識(shí)。接下來是訪問資源糟趾,其實(shí)就是對(duì)服務(wù)的請(qǐng)求代碼請(qǐng)求進(jìn)行一個(gè)控制慌植,代碼如下:

private static String KEY = "biz"http:// 資源名
public void request() {
    try {
    // token acquired, means pass
    Entry  entry = SphU.entry(KEY);
    //被保護(hù)biz代碼
    } catch (BlockException e1) {
    // 資源訪問阻止,被限流或被降級(jí)
    } catch (Exception e2) {
    // biz exception
    } finally {
        if (entry != null) {
            entry.exit();
        }
    }
}  

這里可以看出所謂的資源其實(shí)就是Entry entry = SphU.entry(KEY);代碼后的業(yè)務(wù)代碼义郑,并且Sentinel通過一個(gè)KEY作為它的唯一表示蝶柿。

SphU的entry() 方法,將返回KEY的調(diào)用的信息非驮。 當(dāng)超過任何規(guī)則的閾值時(shí)交汤。 將拋出BlockException。進(jìn)入catch BlockException 代碼塊劫笙。

下面是參考官網(wǎng)的的一個(gè)完整的例子:

public class FlowQpsDemo {

    private static final String KEY = "abc";

    private static AtomicInteger pass = new AtomicInteger();
    private static AtomicInteger block = new AtomicInteger();
    private static AtomicInteger total = new AtomicInteger();
    private static volatile boolean stop = false;

    private static int seconds = 20;

    public static void main(String[] args) {
        initFlowQpsRule();
        //單開一條線程芙扎,統(tǒng)計(jì)流量數(shù)據(jù)
        new Thread(new CountFlowTool()).start();
        //多線程請(qǐng)求
        new simulateFlow(10).start();

    }

    private static void initFlowQpsRule() {
        List<FlowRule> rules = new ArrayList<FlowRule>();
        FlowRule rule1 = new FlowRule();
        rule1.setResource(KEY);
        // set limit qps to 20
        rule1.setCount(20);
        rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule1.setLimitApp("default");
        rule1.setControlBehavior(CONTROL_BEHAVIOR_DEFAULT);
        rules.add(rule1);
        FlowRuleManager.loadRules(rules);
    }


    static class CountFlowTool implements Runnable {
        public void run() {
            long start = System.currentTimeMillis();
            System.out.println("begin to statistic!!!");

            long oldTotal = 0;
            long oldPass = 0;
            long oldBlock = 0;
            while (!stop) {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                }
                long globalTotal = total.get();
                long oneSecondTotal = globalTotal - oldTotal;
                oldTotal = globalTotal;

                long globalPass = pass.get();
                long oneSecondPass = globalPass - oldPass;
                oldPass = globalPass;

                long globalBlock = block.get();
                long oneSecondBlock = globalBlock - oldBlock;
                oldBlock = globalBlock;

                System.out.println(seconds + " send qps is: " + oneSecondTotal);
                System.out.println(TimeUtil.currentTimeMillis() + ", total:" + oneSecondTotal
                        + ", pass:" + oneSecondPass
                        + ", block:" + oneSecondBlock);

                if (seconds-- <= 0) {
                    stop = true;
                }
            }

            long cost = System.currentTimeMillis() - start;
            System.out.println("time cost: " + cost + " ms");
            System.out.println("total:" + total.get() + ", pass:" + pass.get()
                    + ", block:" + block.get());
            System.exit(0);
        }
    }

    static class simulateFlow {
        int threadCount;
        simulateFlow(int threadCount) {
            this.threadCount = threadCount;
        }

        public void start() {
            for (int i = 0; i < threadCount; i++) {
                Thread t = new Thread(new Runnable() {
                    public void run() {
                        while (!stop) {
                            Entry entry = null;
                            try {
                                total.incrementAndGet();
                                entry = SphU.entry(KEY);
                                // token acquired, means pass
                                pass.addAndGet(1);
                            } catch (BlockException e1) {
                                block.incrementAndGet();
                            } catch (Exception e2) {
                                // biz exception
                            } finally {
                                if (entry != null) {
                                    entry.exit();
                                }
                            }
                            try {
                                TimeUnit.MILLISECONDS.sleep(20);
                            } catch (InterruptedException e) {
                            }
                        }
                    }
                });
                t.start();
            }
        }
    }
}

主方法中顯示定義規(guī)則,讓后通過多線程模擬請(qǐng)求填大,內(nèi)部通過循環(huán)不停的請(qǐng)求資源戒洼。統(tǒng)計(jì)工具是統(tǒng)計(jì)前一秒的請(qǐng)求數(shù)據(jù)≡驶總體代碼比較直觀易懂圈浇。

根據(jù)線程數(shù)的流量限制也是類似。只是規(guī)則設(shè)置代碼不同靴寂。還有一個(gè)問題就是根據(jù)線程數(shù)的流量限制中汉额,Sentinel沒有對(duì)線程的控制權(quán)限,內(nèi)部只是對(duì)請(qǐng)求線程的統(tǒng)計(jì)榨汤。如果超出閾值蠕搜,新的請(qǐng)求會(huì)被立即拒絕。但是根據(jù)QPS進(jìn)行流量控制中可以有多個(gè)選擇:1. 直接拒絕(CONTROL_BEHAVIOR_DEFAULT)收壕,2. 慢啟動(dòng)也叫冷啟動(dòng)(CONTROL_BEHAVIOR_WARM_UP)過"冷啟動(dòng)"妓灌,讓通過的流量緩慢增加,在一定時(shí)間內(nèi)逐漸增加到閾值上限蜜宪,給冷系統(tǒng)一個(gè)預(yù)熱的時(shí)間虫埂,避免冷系統(tǒng)被壓垮的情況。圃验,3. 勻速通過(CONTROL_BEHAVIOR_RATE_LIMITER)掉伏,這種方式嚴(yán)格控制了請(qǐng)求通過的間隔時(shí)間,也即是讓請(qǐng)求以均勻的速度通過,內(nèi)部實(shí)現(xiàn)是漏桶算法斧散。

4. 熔斷降級(jí)

Sentinel中供常,對(duì)資源的調(diào)用都自動(dòng)熔斷。通常用兩種方式來衡量資源是否處于穩(wěn)定的狀態(tài):RT和異常鸡捐。以平均響應(yīng)時(shí)間為例栈暇,如果請(qǐng)求的的時(shí)間大于閾值,那么接下來會(huì)嘗試5次箍镜,如果這5次的請(qǐng)求時(shí)間平均時(shí)間大于閾值源祈,那么在接下來的時(shí)間窗口(timeWindow)內(nèi)將自動(dòng)降級(jí)處理(直接跳入BlockException),當(dāng)時(shí)間窗口結(jié)束再次嘗試5次色迂,以此重復(fù)香缺。這里嘗試五次的觸發(fā)點(diǎn)是RT超過閾值。
下面結(jié)合Demo講解,這里指列出規(guī)則定義的代碼:

  private static void initDegradeRule() {
    List<DegradeRule> rules = new ArrayList<DegradeRule>();
    DegradeRule rule = new DegradeRule();
    rule.setResource(KEY);
    // 設(shè)置響應(yīng)時(shí)間歇僧,50ms
    rule.setCount(50);
    rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
    rule.setTimeWindow(5);
    rules.add(rule);
    DegradeRuleManager.loadRules(rules);
  }

通過異常降級(jí)于此類似赫悄。當(dāng)資源的每秒異常總數(shù)占通過總數(shù)的比值超過閾值(DegradeRule 中的 count)之后馏慨,資源進(jìn)入降級(jí)狀態(tài),即在接下的時(shí)間窗口(DegradeRule 中的 timeWindow姑隅,以 s 為單位)之內(nèi)写隶,對(duì)這個(gè)方法的調(diào)用都會(huì)自動(dòng)地返回。

下面參考官網(wǎng)給出一個(gè)完整的基于RT熔斷的例子:

public class RtDegradeDemo {

  private static final String KEY = "abc";

  private static AtomicInteger pass = new AtomicInteger();
  private static AtomicInteger block = new AtomicInteger();
  private static AtomicInteger total = new AtomicInteger();
  private static int seconds = 10000;
  private static boolean stop = false;

  public static void main(String[] args) throws Exception {
    initDegradeRule();
    new Thread(new CountFlowTool()).start();
    new simulateFlow(1).start();
  }

  private static void initDegradeRule() {
    List<DegradeRule> rules = new ArrayList<DegradeRule>();
    DegradeRule rule = new DegradeRule();
    rule.setResource(KEY);
    rule.setCount(50);
    rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
    rule.setTimeWindow(10);
    rules.add(rule);
    DegradeRuleManager.loadRules(rules);
  }

  static class simulateFlow {

    int threadCount;

    public simulateFlow(int threadCount) {
      this.threadCount = threadCount;
    }

    public void start() {
      for (int i = 0; i < threadCount; i++) {
        new Thread(() -> {
          while (!stop) {
            Entry entry = null;
            try {
              total.incrementAndGet();
              TimeUnit.MILLISECONDS.sleep(100);
              entry = SphU.entry(KEY);
              pass.getAndIncrement();
              TimeUnit.MILLISECONDS.sleep(100);
            } catch (BlockException e) {
              block.incrementAndGet();
            } catch (Throwable e) {
              //biz exception
            } finally {
              if (entry != null) {
                entry.exit();
              }
            }
          }
        }).start();
      }
    }
  }

  static class CountFlowTool implements Runnable {

    public void run() {
      long start = System.currentTimeMillis();
      System.out.println("begin to statistic!!!");

      long oldTotal = 0;
      long oldPass = 0;
      long oldBlock = 0;
      while (!stop) {
        try {
          TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
        }
        long globalTotal = total.get();
        long oneSecondTotal = globalTotal - oldTotal;
        oldTotal = globalTotal;

        long globalPass = pass.get();
        long oneSecondPass = globalPass - oldPass;
        oldPass = globalPass;

        long globalBlock = block.get();
        long oneSecondBlock = globalBlock - oldBlock;
        oldBlock = globalBlock;

        System.out.println(TimeUtil.currentTimeMillis() + ", laseSec total:" + oneSecondTotal
            + ", pass:" + oneSecondPass
            + ", block:" + oneSecondBlock);

        if (seconds-- <= 0) {
          stop = true;
        }
      }

      long cost = System.currentTimeMillis() - start;
      System.out.println("time cost: " + cost + " ms");
      System.out.println("total:" + total.get() + ", pass:" + pass.get()
          + ", block:" + block.get());
      System.exit(0);
    }
  }
}

5. 控制臺(tái)

Sentinel提供了控制臺(tái)模塊讲仰,用于對(duì)實(shí)時(shí)限流熔斷數(shù)據(jù)的可視化和對(duì)規(guī)則(限流和熔斷)的實(shí)時(shí)推送慕趴。控制臺(tái)是一個(gè)基于Spring boot開發(fā)的控制臺(tái)鄙陡。其主要流程為:

  1. 控制臺(tái)工程啟動(dòng)
  2. APP啟動(dòng)冕房,向控制臺(tái)發(fā)送心跳數(shù)據(jù)(APP信息包括機(jī)器信息、APP name等)趁矾,可以從代碼找到:
public class Env {

    public static final NodeBuilder nodeBuilder = new DefaultNodeBuilder();
    public static final Sph sph = new CtSph();

    static {
        // If init fails, the process will exit.
        InitExecutor.doInit();// doInit方法會(huì)調(diào)用sendHeadBeat
    }

}
  1. 前端發(fā)送HTTP請(qǐng)求(請(qǐng)求規(guī)則耙册、實(shí)時(shí)運(yùn)行數(shù)據(jù)) -> 控制臺(tái)HTTP請(qǐng)求-> APP Netty Server

搭建控制臺(tái)步驟:

  1. 啟動(dòng)控制臺(tái)工程,有兩種方式直接運(yùn)行Jar包和在源碼中啟動(dòng)SpringBoot毫捣,筆者在這里介紹后者详拙。代碼工程如下:
    Sentinel

    添加如下參數(shù):-Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard
    2 . 啟動(dòng)APP應(yīng)用,參數(shù)如下:-Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=demo
    maven 依賴:
    <dependencies>
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-core</artifactId>
            <version>0.2.1</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-transport-simple-http</artifactId>
            <version>0.2.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

恭喜你蔓同!


控制臺(tái)

6. 總結(jié)

本文主要介紹了Sentinel的限流和熔斷降級(jí)功能饶辙,但是Sentinel的功能不止于此。比如系統(tǒng)負(fù)載保護(hù)斑粱,系統(tǒng)負(fù)載高于某個(gè)閾值弃揽,就禁止或者減少流量的進(jìn)入;當(dāng) load 開始好轉(zhuǎn),則恢復(fù)流量的進(jìn)入矿微。以及對(duì)注解的支持痕慢、控制面板等。

相比Hystrix來說冷冗,Sentinel的熔斷和限流邏輯更簡(jiǎn)單明了守屉。后續(xù)會(huì)出Sentinel的實(shí)現(xiàn)原理文章。

參考:https://github.com/alibaba/Sentinel/wiki

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蒿辙,一起剝皮案震驚了整個(gè)濱河市拇泛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌思灌,老刑警劉巖俺叭,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異泰偿,居然都是意外死亡熄守,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門耗跛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來裕照,“玉大人,你說我怎么就攤上這事调塌〗希” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵羔砾,是天一觀的道長(zhǎng)负间。 經(jīng)常有香客問我,道長(zhǎng)姜凄,這世上最難降的妖魔是什么政溃? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮态秧,結(jié)果婚禮上董虱,老公的妹妹穿的比我還像新娘。我一直安慰自己申鱼,他們只是感情好空扎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著润讥,像睡著了一般转锈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上楚殿,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天撮慨,我揣著相機(jī)與錄音竿痰,去河邊找鬼。 笑死砌溺,一個(gè)胖子當(dāng)著我的面吹牛影涉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播规伐,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蟹倾,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了猖闪?” 一聲冷哼從身側(cè)響起鲜棠,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎培慌,沒想到半個(gè)月后豁陆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吵护,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年盒音,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片馅而。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡祥诽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瓮恭,到底是詐尸還是另有隱情雄坪,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布偎血,位于F島的核電站,受9級(jí)特大地震影響盯漂,放射性物質(zhì)發(fā)生泄漏颇玷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一就缆、第九天 我趴在偏房一處隱蔽的房頂上張望帖渠。 院中可真熱鬧,春花似錦竭宰、人聲如沸空郊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽狞甚。三九已至,卻和暖如春廓旬,著一層夾襖步出監(jiān)牢的瞬間哼审,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留涩盾,地道東北人十气。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像春霍,于是被迫代替她去往敵國和親砸西。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 這是圍繞 Sentinel 的使用場(chǎng)景址儒、技術(shù)對(duì)比和實(shí)現(xiàn)芹枷、開發(fā)者實(shí)踐等維度推出的系列文章的第三篇。 第一篇回顧: D...
    夜風(fēng)月圓閱讀 31,233評(píng)論 3 69
  • 原文鏈接: 技術(shù)選型:Sentinel vs Hystrix Hystrix之外健壯微服務(wù)的新選擇:Sentine...
    專職跑龍?zhí)?/span>閱讀 6,946評(píng)論 0 14
  • 概述 Sentinel譯為“哨兵”离福,顧名思義杖狼,面對(duì)您后臺(tái)的大量服務(wù)/微服務(wù),前置一個(gè)哨兵妖爷,但面對(duì)大量請(qǐng)求時(shí)蝶涩,讓后臺(tái)...
    空山雪林閱讀 21,847評(píng)論 0 3
  • 在中國,眾多佛教和道教的典籍中都有斷食辟谷的方法和功效絮识。它是修行人提升身心素質(zhì)绿聘、檢驗(yàn)修煉境界的重要手段。歷...
    微微修仙派閱讀 2,060評(píng)論 0 0
  • 今天有學(xué)生家長(zhǎng)告訴我老師讓帶積木次舌。我問女兒熄攘,她居然什么也不知道,不知道是不是上課沒聽講彼念。我告訴她袋子里我給裝了六塊...
    陳俞含0_0閱讀 75評(píng)論 0 0