Sentinel-Go 集成 Nacos 实现外部动态数据源
Go语言精选
共 3991字,需浏览 8分钟
·
2020-10-01 08:09
导读: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 main
import (
"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.git
cd nacos/
mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U
ls -al distribution/target/
// change the $version to your actual path
cd distribution/target/nacos-server-$version/nacos/bin
nacos-server-$version.zip
包。unzip nacos-server-$version.zip 或者 tar -xvf nacos-server-$version.tar.gz
cd nacos/bin
4)启动服务器
Linux/Unix/Mac
sh startup.sh -m standalone
bash startup.sh -m standalone
Windows
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-example
go 1.13
require (
v0.6.0
v1.0.0
)
main.go
package main
import (
"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 *int64
block *int64
total *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-go
cc := 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
}
//注册流控规则Handler
h := datasource.NewFlowRulesHandler(datasource.FlowRuleJsonArrayParser)
//创建NacosDataSource数据源
//sentinel-go 对应在nacos中创建配置文件的group
//flow 对应在nacos中创建配置文件的dataId
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
}
//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 流控配置文件中的resource
e, 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 print
func 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 - oldTotal
oldTotal = globalTotal
globalPass := atomic.LoadInt64(counter.pass)
oneSecondPass := globalPass - oldPass
oldPass = globalPass
globalBlock := atomic.LoadInt64(counter.block)
oneSecondBlock := globalBlock - oldBlock
oldBlock = globalBlock
fmt.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 微服务生态中的推广集成工作。
推荐阅读
评论