Sentinel集群限流

準備工作

基于sentine-1.4.2扑馁,在dashboard想要更好的查看集群限流相關配置百侧,需要一些小修改

你也可以直接從github上拉取我的代碼: git@github.com:spilledyear/Sentinel.git,對應的分支是 1.4.2

  • 開啟集群規(guī)則界面
    修改:resources/app/views/flow_v1.html棍厂,將其中和集群相關的按鈕打開,最終效果如下:


  • 規(guī)則持久化
    dashboard默認沒有對規(guī)則持久化,但在集群規(guī)則界面添加的規(guī)則锦援,其實是可以持久化到nacos的,只需要做一些簡單的修改剥悟。將dashboard模塊test目錄下的com.alibaba.csp.sentinel.dashboard.rule.nacos類拷貝到java目錄灵寺,如下:



    然后修改com.alibaba.csp.sentinel.dashboard.controller.v2.FlowControllerV2文件,將其中的ruleProvider和rulePublisher改成剛剛新增的那兩個


  • 啟動nacos
    nacos的部署就不過多介紹区岗,可以看官方文檔 nacos手冊

下面將從以下幾個方面簡單介紹集群限流

啟動測試案例

以嵌入式模式為例略板,在源碼的sentinel-demo模塊種,已經(jīng)準備好了相關測試案例慈缔,啟動兩個實例:ClusterDemoApplication叮称,啟動參數(shù)分別如下:

  • 實例一
-Dproject.name=clusterapp -Dserver.port=8081 -Dcsp.sentinel.dashboard.server=localhost:8080
  • 實例二
-Dproject.name=clusterapp -Dserver.port=8082 -Dcsp.sentinel.dashboard.server=localhost:8080

為了能夠方便的修改規(guī)則信息,直觀的觀察效果藐鹤,需要啟動控制臺

  • 啟動控制臺
-Dserver.port=8080

此時通過localhost:8080訪問控制臺瓤檐,還無法看到任何應用信息,因為此時還沒有任何的服務調(diào)用娱节,通過以下快捷方式訪問兩個服務實例

curl localhost:8081/hello/luo

curl localhost:8082/hello/luo

這時候查看機器列表菜單選項挠蛉,發(fā)現(xiàn)已經(jīng)有兩個實例了(端口區(qū)分):

但這時候還沒有server和client的概念,需要簡單配置:點擊集群限流菜單項括堤,然后點擊右上角的"新增Toeken Server"


從中選取一臺server碌秸,另一臺指定為client,即:

此時悄窃,再查看集群流控菜單項讥电,發(fā)現(xiàn)已經(jīng)有了server信息,通過連接詳情發(fā)現(xiàn)已有兩個連接轧抗,這是這是嵌入式恩敌,server端本身也是一個應用實例

規(guī)則的推送

新建規(guī)則

以上準備工作完成之后,下面可以新建資源了横媚。為了觀察限流效果光差纠炮,新建的資源名與測試案例中的資源名一致:點擊流控規(guī)則菜單項月趟,然后點擊右上角的回到集群界面

為什么這里要在集群界面新建規(guī)則呢?上面已經(jīng)說過了恢口,針對集群規(guī)則界面已經(jīng)做了修改孝宗,規(guī)則可以持久化到nacos配置中心



然后新建一個規(guī)則,有關于規(guī)則的使用這里就不展開了


以上操作完成之后耕肩,會發(fā)現(xiàn)nacos中多了一條配置因妇,具體內(nèi)容就是規(guī)則的具體信息

查看限流效果

通過jmeter測試,讓兩個請求都分別請求不同的實例各20次:

發(fā)現(xiàn)每個請求都通過了10次猿诸,加起來剛好20次婚被,多出來的請求拋出了FlowException異常,執(zhí)行了blockHandler對應的邏輯梳虽,初步符合集群限流的效果

推送原理

在保存規(guī)則信息的時候址芯,發(fā)現(xiàn)請求了以下接口:http://localhost:8080/v2/flow/rule/29
對應FlowControllerV2中的apiUpdateFlowRule,主要邏輯如下:

  • 將規(guī)則信息更新到dashboard的內(nèi)存中窜觉,用于界面展示谷炸,這一部分主要和InMemoryRuleRepositoryAdapter的save方法相關;
  • 推送規(guī)則信息到nacos注冊中心禀挫,這一部分和FlowRuleNacosPublisher相關淑廊;

如果dashboard使用了nacos持久化規(guī)則,對應的,在嵌入式模式下應該也會在server和client端使用NacosDatasource作為數(shù)據(jù)源特咆,對應的源碼在sentinel-datasource-nacos模塊的NacosDataSource類中:

public NacosDataSource(final Properties properties, final String groupId, final String dataId,Converter<String, T> parser) {
    super(parser);
    this.configListener = new Listener() {
        @Override
        public Executor getExecutor() {
            return pool;
        }
        @Override
        public void receiveConfigInfo(final String configInfo) {
            RecordLog.info(String.format("[NacosDataSource] New property value received for (properties: %s) (dataId: %s, groupId: %s): %s",
                properties, dataId, groupId, configInfo));
            T newValue = NacosDataSource.this.parser.convert(configInfo);
            // Update the new value to the property.
            getProperty().updateValue(newValue);
        }
    };
    initNacosListener();
    loadInitialConfig();
}

從上可以看出季惩,當規(guī)則信息更新了的時候,會同步到sentinel的內(nèi)存結構中腻格。

這里有一個小問題画拾,如果沒有使用注冊中心,規(guī)則將怎么進行推送菜职?
答案其實在FlowRuleApiPublisher中青抛,如果沒有使用注冊中心,將通過SentinelApiClient發(fā)送http請求酬核,將規(guī)則推送到各個服務實例蜜另,服務實例收到規(guī)則信息之后再加載到sentinel相關的內(nèi)存結構,核心代碼如下:

for (MachineInfo machine : set) {
    if (!MachineUtils.isMachineHealth(machine)) {
        continue;
    }
    // TODO: parse the results
    sentinelApiClient.setFlowRuleOfMachine(app, machine.getIp(), machine.getPort(), rules);
}

如果針對這個問題再次延申嫡意,還會有一些疑問举瑰,SentinelApiClient怎么就知道要將規(guī)則信息發(fā)送到哪里呢?哪個端口蔬螟?這一部分肯定是sentine為我們隱藏起來了此迅。

  • 第一個問題,哪個端口?這個端口其實是commandPort耸序,即應用端暴露給 Sentinel 控制臺的端口忍些,ip@commandPort,其實就是界面上看到的那兩個坎怪,分別為8720和8721罢坝;

  • 第二個問題,隱藏了哪些細節(jié)搅窿?其實就是隱藏了暴露端口的這部分細節(jié)炸客,都在sentinel-transport模塊中,提供了兩種實現(xiàn)方式戈钢。

  • 方式一,sentinel-transport-simple-http模塊中是尔,通過ServerSocket方式暴露殉了,對應的核心類為SimpleHttpCommandCenter,核心代碼如下

@Override
public void run() {
    boolean success = false;
    ServerSocket serverSocket = getServerSocketFromBasePort(port);

    if (serverSocket != null) {
        CommandCenterLog.info("[CommandCenter] Begin listening at port " + serverSocket.getLocalPort());
        socketReference = serverSocket;
        executor.submit(new ServerThread(serverSocket));
        success = true;
        port = serverSocket.getLocalPort();
    } else {
        CommandCenterLog.info("[CommandCenter] chooses port fail, http command center will not work");
    }

    if (!success) {
        port = PORT_UNINITIALIZED;
    }

    TransportConfig.setRuntimePort(port);
    executor.shutdown();
}
  • 方式二拟枚,在sentinel-transport-netty-http模塊中薪铜,通過netty暴露,核心類是NettyHttpCommandCenter恩溅,核心代碼如下:
@Override
public void start() throws Exception {
    pool.submit(new Runnable() {
        @Override
        public void run() {
            try {
                server.start();
            } catch (Exception ex) {
                RecordLog.info("Start netty server error", ex);
                ex.printStackTrace();
                System.exit(-1);
            }
        }
    });
}

內(nèi)部通過SPI機制加載隔箍,引用了哪個模塊就會使用哪種機制。

節(jié)點發(fā)現(xiàn)

dashboard是如何獲取節(jié)點信息并將其展示在界面上的脚乡?核心原理還是在sentinel-transport模塊中蜒滩,不管是在sentinel-transport-simple-http還是sentinel-transport-netty-http中,都會向dashboard發(fā)送心跳上報當前節(jié)點信息奶稠,請求地址即:

dashboardIp:port/registry/machine俯艰,這里代表 localhost:8080/registry/machine

dashboar收到請求后會將節(jié)點信息保存到內(nèi)存中。

有關于這一部分锌订,sentinel-transport-simple-http模塊中的核心類是SimpleHttpHeartbeatSender竹握;sentinel-transport-netty-http模塊中的核心類是HttpHeartbeatSender;

dashboard相關的邏輯如下

public Result<?> receiveHeartBeat(String app, Long version, String v, String hostname, String ip, Integer port) {
    if (app == null) {
        app = MachineDiscovery.UNKNOWN_APP_NAME;
    }
    if (ip == null) {
        return Result.ofFail(-1, "ip can't be null");
    }
    if (port == null) {
        return Result.ofFail(-1, "port can't be null");
    }
    if (port == -1) {
        logger.info("Receive heartbeat from " + ip + " but port not set yet");
        return Result.ofFail(-1, "your port not set yet");
    }
    String sentinelVersion = StringUtil.isEmpty(v) ? "unknown" : v;
    long timestamp = version == null ? System.currentTimeMillis() : version;
    try {
        MachineInfo machineInfo = new MachineInfo();
        machineInfo.setApp(app);
        machineInfo.setHostname(hostname);
        machineInfo.setIp(ip);
        machineInfo.setPort(port);
        machineInfo.setTimestamp(new Date(timestamp));
        machineInfo.setVersion(sentinelVersion);
        appManagement.addMachine(machineInfo);
        return Result.ofSuccessMsg("success");
    } catch (Exception e) {
        logger.error("Receive heartbeat error", e);
        return Result.ofFail(-1, e.getMessage());
    }
}

所以辆飘,整個過程看起來是這樣子的:


配置項

  • NameSpace
    NameSpace主要是用于區(qū)分不同的應用啦辐,其實在嵌入式的模式下作用不大,嵌入式模式下一般是一種對等結構蜈项,這時候NameSpace一般就是一個芹关,即:應用名。只有在獨立模式下才能體現(xiàn)它的作用:區(qū)分不同的應用紧卒。
// 如果不配置默認default
ClusterServerConfigManager.loadServerNamespaceSet(Collections.singleton("cluster-" + appId));
  • Supplier
    主要作用就是就是根據(jù)NameSpace找到一個DynamicSentinelProperty充边,其實在嵌入式模式下,一般也就是寫死一個DynamicSentinelProperty,因為這時候的NameSpace也就只有一個
// 集群限流規(guī)則配置浇冰,根據(jù)namespace動態(tài)生成Supplier贬媒,其實子
ClusterFlowRuleManager.setPropertySupplier(dataSource.getClusterFlowSupplier());
  • ServerTransportProperty
    作用比較大,針對server端肘习,會根據(jù)ServerTransportProperty中的信息在server端通過netty開啟一個端口际乘,用于和client交互
// 配置ServerTransportConfig:port、idleSeconds
ClusterServerConfigManager.registerServerTransportProperty(dataSource.getServerTransportConfigProperty());
  • ClientConfigProperty
    client端的相關配置漂佩,其實只有一個屬性:請求server端的超時時間(requestTimeout)
// 為client設置requestTimeout
ClusterClientConfigManager.registerClientConfigProperty(dataSource.getClusterClientConfigProperty());
  • ServerAssignProperty
    client端的相關配置脖含,里面保存的是server端的相關信息:server的host和port
// 為client設置server的host和port,即serverHost投蝉、serverPort
ClusterClientConfigManager.registerServerAssignProperty(dataSource.getClusterClientAssignConfigProperty());
  • ClusterStateManager
    在嵌入式模式下养葵,可以通過API來改變client和server的身份,大致邏輯就是:將server中的那個netty服務stop瘩缆,然后根據(jù)新的配置在client開啟一個新的netty服務(注意关拒,服務開啟成功之后,client就轉(zhuǎn)變成server了)
// 用于設置mode庸娱,設置0 代表client着绊, 設置1代表 server
ClusterStateManager.registerProperty(dataSource.getClusterStateProperty());
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市熟尉,隨后出現(xiàn)的幾起案子归露,更是在濱河造成了極大的恐慌,老刑警劉巖斤儿,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件剧包,死亡現(xiàn)場離奇詭異,居然都是意外死亡往果,警方通過查閱死者的電腦和手機玄捕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來棚放,“玉大人枚粘,你說我怎么就攤上這事∑牵” “怎么了馍迄?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長局骤。 經(jīng)常有香客問我攀圈,道長,這世上最難降的妖魔是什么峦甩? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任赘来,我火速辦了婚禮现喳,結果婚禮上,老公的妹妹穿的比我還像新娘犬辰。我一直安慰自己嗦篱,他們只是感情好,可當我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布幌缝。 她就那樣靜靜地躺著灸促,像睡著了一般。 火紅的嫁衣襯著肌膚如雪涵卵。 梳的紋絲不亂的頭發(fā)上浴栽,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天,我揣著相機與錄音轿偎,去河邊找鬼典鸡。 笑死,一個胖子當著我的面吹牛坏晦,可吹牛的內(nèi)容都是我干的萝玷。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼英遭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了亦渗?” 一聲冷哼從身側響起挖诸,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎法精,沒想到半個月后多律,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡搂蜓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年狼荞,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帮碰。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡相味,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出殉挽,到底是詐尸還是另有隱情丰涉,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布斯碌,位于F島的核電站一死,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏傻唾。R本人自食惡果不足惜投慈,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧伪煤,春花似錦加袋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蝙砌,卻和暖如春阳堕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背择克。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工恬总, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人肚邢。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓壹堰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親骡湖。 傳聞我的和親對象是個殘疾皇子贱纠,可洞房花燭夜當晚...
    茶點故事閱讀 45,435評論 2 359

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

  • 逅弈 轉(zhuǎn)載請注明原創(chuàng)出處,謝謝响蕴! 系列文章 Sentinel 原理-全解析Sentinel 原理-調(diào)用鏈Senti...
    逅弈閱讀 38,619評論 5 34
  • 今天去見了一個客戶谆焊,對事業(yè)的認知,對經(jīng)驗的認知浦夷,有了一個新高度辖试,感謝今天領導陪我去見客戶,做小客戶是在談產(chǎn)品劈狐,但是...
    真心日記閱讀 177評論 3 3
  • 2018年11月14日 今天是去參加人生的第五場葬禮罐孝,是我成人后在外地的第一場,昨夜和沒有睡一樣肥缔,不記得腦袋里想的...
    fairly魚閱讀 146評論 0 0
  • 提到lambda表達式莲兢,就不得不提一下函數(shù)式表達式。函數(shù)式表達式與面向?qū)ο缶幊痰淖畲髤^(qū)別是面向?qū)ο缶幊淌菍?shù)據(jù)進行...
    程自舟閱讀 1,256評論 0 2
  • 得好好總結一篇游記续膳,以餉各位親朋怒见。先要感謝嵐源資本亞楠的盛情相邀,藍途體育的云那細心安排姑宽。還有老天也夠幫忙遣耍,周六還...
    ThisisDaniel閱讀 1,340評論 0 0