Sentinel-Go 集成 Nacos 实现外部动态数据源

导读:2020 年,Sentinel 推出 Go 原生版本 Sentinel-Golang,在云原生领域继续突破。本文将从实际出发结合案例说明在 Sentinel-Golang 中如何集成 Nacos,使其作为外部动态数据源,将流控规则存储在 nacos 中,并且实现动态实时更新规则。
将 sentinel 流控规则定义在代码内部实现限流效果; 将 sentinel 流控规则定义在 nacos 配置中心,实现限流效果以及在 nacos 中动态更新规则,实现动态流控。 

Sentinel
丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等; 
完备的实时监控:Sentinel 同时提供实时的监控功能,您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况; 
广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel; 
完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑,例如定制规则管理、适配动态数据源等。 
Sentinel 的历史
2012 年,Sentinel 诞生,主要功能为入口流量控制; 
2013-2017 年,Sentinel 在阿里巴巴集团内部迅速发展,成为基础技术模块,覆盖了所有的核心场景,Sentinel 也因此积累了大量的流量归整场景以及生产实践; 
2018 年,Sentinel 开源,并持续演进; 
2019 年,Sentinel 在多语言扩展的方向上逐步探索,陆续推出 C++ 原生版本、Envoy 集群流量控制支持; 
2020 年,Sentinel 推出 Go 原生版本,期待在云原生领域继续突破,地址:https://github.com/alibaba/sentinel-golang 

Nacos


Sentinel-Go 限流 Demo
1. 安装
2. Demo 样例
对 Sentinel 进行相关配置并进行初始化 埋点(定义资源) 配置规则 
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)预备环境准备
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)启动服务器
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 创建时可以自定义,本文创建的 dataId=flow,group=sentinel-go); 将数据源样例粘贴到配置内容中。 
1)Nacos 外部数据源样例
[{"resource": "some-test","metricType": 1,"count": 100.0,"controlBehavior":0}]

3. Nacos 数据源集成
1)创建项目
版本: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() {//流量计数器,为了流控打印日志更直观,和集成nacos数据源无关。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 相关参数配置,具体配置可参考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}//注册流控规则Handlerh := datasource.NewFlowRulesHandler(datasource.FlowRuleJsonArrayParser)//创建NacosDataSource数据源//sentinel-go 对应在nacos中创建配置文件的group//flow 对应在nacos中创建配置文件的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数据源初始化err = nds.Initialize()if err != nil {fmt.Printf("Fail to initialize nacos data source client, err: %+v", err)return}//启动统计go timerTask(&counter)//模拟流量ch := make(chan struct{})for i := 0; i < 10; i++ {go func() {for {atomic.AddInt64(counter.total, 1)//some-test 对应在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)运行结果

3)动态更新限流配置



总结
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}
相关链接:
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 项目地址:https://github.com/nacos-group/nacos-sdk-go 
作者简介
张斌斌 Github 账号:sanxun0325, Nacos Commiter,Sentinel-Golang Contributor,现任职 OpenJaw 微服务团队。目前主要负责 Nacos,Sentinel-Golang 社区相关项目的开发工作,以及 Nacos 在 Golang 微服务生态中的推广集成工作。
推荐阅读

评论
