Sentinel-Go 集成 Nacos 實(shí)現(xiàn)外部動態(tài)數(shù)據(jù)源

導(dǎo)讀:2020?年,Sentinel 推出 Go 原生版本?Sentinel-Golang,在云原生領(lǐng)域繼續(xù)突破。本文將從實(shí)際出發(fā)結(jié)合案例說明在 Sentinel-Golang?中如何集成?Nacos,使其作為外部動態(tài)數(shù)據(jù)源,將流控規(guī)則存儲在?nacos 中,并且實(shí)現(xiàn)動態(tài)實(shí)時(shí)更新規(guī)則。
將 sentinel 流控規(guī)則定義在代碼內(nèi)部實(shí)現(xiàn)限流效果; 將 sentinel 流控規(guī)則定義在 nacos 配置中心,實(shí)現(xiàn)限流效果以及在 nacos 中動態(tài)更新規(guī)則,實(shí)現(xiàn)動態(tài)流控。

Sentinel
豐富的應(yīng)用場景:Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發(fā)流量控制在系統(tǒng)容量可以承受的范圍)、消息削峰填谷、集群流量控制、實(shí)時(shí)熔斷下游不可用應(yīng)用等;
完備的實(shí)時(shí)監(jiān)控:Sentinel 同時(shí)提供實(shí)時(shí)的監(jiān)控功能,您可以在控制臺中看到接入應(yīng)用的單臺機(jī)器秒級數(shù)據(jù),甚至 500 臺以下規(guī)模的集群的匯總運(yùn)行情況;
廣泛的開源生態(tài):Sentinel 提供開箱即用的與其它開源框架/庫的整合模塊,例如與 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相應(yīng)的依賴并進(jìn)行簡單的配置即可快速地接入 Sentinel;
完善的 SPI 擴(kuò)展點(diǎn):Sentinel 提供簡單易用、完善的 SPI 擴(kuò)展接口。您可以通過實(shí)現(xiàn)擴(kuò)展接口來快速地定制邏輯,例如定制規(guī)則管理、適配動態(tài)數(shù)據(jù)源等。
Sentinel 的歷史
2012 年,Sentinel 誕生,主要功能為入口流量控制;
2013-2017 年,Sentinel 在阿里巴巴集團(tuán)內(nèi)部迅速發(fā)展,成為基礎(chǔ)技術(shù)模塊,覆蓋了所有的核心場景,Sentinel 也因此積累了大量的流量歸整場景以及生產(chǎn)實(shí)踐;
2018 年,Sentinel 開源,并持續(xù)演進(jìn);
2019 年,Sentinel 在多語言擴(kuò)展的方向上逐步探索,陸續(xù)推出 C++ 原生版本、Envoy 集群流量控制支持;
2020 年,Sentinel 推出 Go 原生版本,期待在云原生領(lǐng)域繼續(xù)突破,地址:https://github.com/alibaba/sentinel-golang

Nacos


Sentinel-Go 限流 Demo
1. 安裝
2. Demo 樣例
對 Sentinel 進(jìn)行相關(guān)配置并進(jìn)行初始化 埋點(diǎn)(定義資源) 配置規(guī)則
package mainimport ("fmt""log""math/rand""time"sentinel "github.com/alibaba/sentinel-golang/api""github.com/alibaba/sentinel-golang/core/base""github.com/alibaba/sentinel-golang/core/flow""github.com/alibaba/sentinel-golang/util")func main() {// We should initialize Sentinel first.err := sentinel.InitDefault()if err != nil {log.Fatalf("Unexpected error: %+v", err)}_, err = flow.LoadRules([]*flow.FlowRule{{Resource: "some-test",MetricType: flow.QPS,Count: 10,ControlBehavior: flow.Reject,},})if err != nil {log.Fatalf("Unexpected error: %+v", err)return}ch := make(chan struct{})for i := 0; i < 10; i++ {go func() {for {e, b := sentinel.Entry("some-test", sentinel.WithTrafficType(base.Inbound))if b != nil {// Blocked. We could get the block reason from the BlockError.time.Sleep(time.Duration(rand.Uint64()%10) * time.Millisecond)} else {// Passed, wrap the logic here.fmt.Println(util.CurrentTimeMillis(), "passed")time.Sleep(time.Duration(rand.Uint64()%10) * time.Millisecond)// Be sure the entry is exited finally.e.Exit()}}}()}<-ch}

Sentinel-Go 集成 Nacos
1. 部署?Nacos
1)版本選擇
2)預(yù)備環(huán)境準(zhǔn)備
3)下載源碼或者安裝包
git clone https://github.com/alibaba/nacos.gitcd nacos/mvn -Prelease-nacos -Dmaven.test.skip=true clean install -Uls -al distribution/target/// change the $version to your actual pathcd distribution/target/nacos-server-$version/nacos/bin
nacos-server-$version.zip?包。unzip nacos-server-$version.zip 或者 tar -xvf nacos-server-$version.tar.gzcd nacos/bin
4)啟動服務(wù)器
Linux/Unix/Mac
sh startup.sh -m standalonebash startup.sh -m standaloneWindows
cmd startup.cmd用戶名/密碼:nacos/nacos
2. Sentinel 限流配置到 Nacos
登錄到 nacos web; 在配置管理中,新建配置; 輸入 dataId,group(dataId,group 創(chuàng)建時(shí)可以自定義,本文創(chuàng)建的 dataId=flow,group=sentinel-go); 將數(shù)據(jù)源樣例粘貼到配置內(nèi)容中。
1)Nacos 外部數(shù)據(jù)源樣例
[{"resource": "some-test","metricType": 1,"count": 100.0,"controlBehavior":0}]

3. Nacos 數(shù)據(jù)源集成
1)創(chuàng)建項(xiàng)目
版本:sentinel-golang 版本使用 0.6.0;nacos-sdk-go 使用 1.0.0;
go.mod
module sentinel-go-nacos-examplego 1.13require (v0.6.0v1.0.0)
main.go
package mainimport ("fmt""math/rand""sync/atomic""time"sentinel "github.com/alibaba/sentinel-golang/api""github.com/alibaba/sentinel-golang/core/base""github.com/alibaba/sentinel-golang/ext/datasource/nacos""github.com/alibaba/sentinel-golang/util""github.com/nacos-group/nacos-sdk-go/clients""github.com/alibaba/sentinel-golang/ext/datasource""github.com/nacos-group/nacos-sdk-go/common/constant")type Counter struct {pass *int64block *int64total *int64}func main() {//流量計(jì)數(shù)器,為了流控打印日志更直觀,和集成nacos數(shù)據(jù)源無關(guān)。counter := Counter{pass: new(int64), block: new(int64), total: new(int64)}//nacos server地址sc := []constant.ServerConfig{{ContextPath: "/nacos",Port: 8848,IpAddr: "127.0.0.1",},}//nacos client 相關(guān)參數(shù)配置,具體配置可參考https://github.com/nacos-group/nacos-sdk-gocc := constant.ClientConfig{TimeoutMs: 5000,}//生成nacos config client(配置中心客戶端)client, err := clients.CreateConfigClient(map[string]interface{}{"serverConfigs": sc,"clientConfig": cc,})if err != nil {fmt.Printf("Fail to create client, err: %+v", err)return}//注冊流控規(guī)則Handlerh := datasource.NewFlowRulesHandler(datasource.FlowRuleJsonArrayParser)//創(chuàng)建NacosDataSource數(shù)據(jù)源//sentinel-go 對應(yīng)在nacos中創(chuàng)建配置文件的group//flow 對應(yīng)在nacos中創(chuàng)建配置文件的dataIdnds, err := nacos.NewNacosDataSource(client, "sentinel-go", "flow", h)if err != nil {fmt.Printf("Fail to create nacos data source client, err: %+v", err)return}//nacos數(shù)據(jù)源初始化err = nds.Initialize()if err != nil {fmt.Printf("Fail to initialize nacos data source client, err: %+v", err)return}//啟動統(tǒng)計(jì)go timerTask(&counter)//模擬流量ch := make(chan struct{})for i := 0; i < 10; i++ {go func() {for {atomic.AddInt64(counter.total, 1)//some-test 對應(yīng)在nacos 流控配置文件中的resourcee, b := sentinel.Entry("some-test", sentinel.WithTrafficType(base.Inbound))if b != nil {atomic.AddInt64(counter.block, 1)// Blocked. We could get the block reason from the BlockError.time.Sleep(time.Duration(rand.Uint64()%10) * time.Millisecond)} else {atomic.AddInt64(counter.pass, 1)time.Sleep(time.Duration(rand.Uint64()%10) * time.Millisecond)// Be sure the entry is exited finally.e.Exit()}}}()}<-ch}//statistic printfunc timerTask(counter *Counter) {fmt.Println("begin to statistic!!!")var (oldTotal, oldPass, oldBlock int64)for {time.Sleep(1 * time.Second)globalTotal := atomic.LoadInt64(counter.total)oneSecondTotal := globalTotal - oldTotaloldTotal = globalTotalglobalPass := atomic.LoadInt64(counter.pass)oneSecondPass := globalPass - oldPassoldPass = globalPassglobalBlock := atomic.LoadInt64(counter.block)oneSecondBlock := globalBlock - oldBlockoldBlock = globalBlockfmt.Println(util.CurrentTimeMillis()/1000, "total:", oneSecondTotal, " pass:", oneSecondPass, " block:", oneSecondBlock)}}
2)運(yùn)行結(jié)果

3)動態(tài)更新限流配置



總結(jié)
h := datasource.NewFlowRulesHandler(datasource.FlowRulesJsonConverter)nds, err := nacos.NewNacosDataSource(client, "sentinel-go", "flow", h)if err != nil {fmt.Printf("Fail to create nacos data source client, err: %+v", err)return}err = nds.Initialize()if err != nil {fmt.Printf("Fail to initialize nacos data source client, err: %+v", err)return}
相關(guān)鏈接:
Demo 地址:https://github.com/alibaba/sentinel-golang/tree/master/example/nacos
Sentinel-golang:https://github.com/alibaba/sentinel-golang
Nacos:https://nacos.io/zh-cn/index.html
Nacos-SDK-Go 項(xiàng)目地址:https://github.com/nacos-group/nacos-sdk-go
作者簡介
張斌斌? Github 賬號:sanxun0325, Nacos Commiter,Sentinel-Golang Contributor,現(xiàn)任職 OpenJaw 微服務(wù)團(tuán)隊(duì)。目前主要負(fù)責(zé) Nacos,Sentinel-Golang 社區(qū)相關(guān)項(xiàng)目的開發(fā)工作,以及 Nacos 在 Golang 微服務(wù)生態(tài)中的推廣集成工作。
推薦閱讀

評論
圖片
表情
