Sentinel-Go 源码系列(一)|开篇
大家好呀,打算写一个 Go 语言组件源码分析系列,一是为了能学习下 Go 语言,看下别人是怎么写 Go 的,二是也掌握一个组件。
本次选择了 Sentinel-Go,一是对 Java 版本的 Sentinel 算是有一些了解,也在生产上落地过,二是感觉他的代码应该不会太复杂(仅仅是感觉),三是在云原生越来越热的趋势下,用 Go 实现的限流降级容错应该是比较通用的。
源码阅读本身是枯燥的,我尽量用容易理解的语言来描述,希望大家也多支持我的文章,点个赞
、在看
和关注
就是对我最大的支持。
背景
Sentinel 简介
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统自适应保护等多个维度来帮助您保障微服务的稳定性。
Sentinel 是阿里2018年开源的项目,最初是 Java 版本,截止目前有 17.6k 的star,项目地址为
2020年又开源了 Go 的版本,目的是朝云原生方向演进,截止目前 1.7k star,项目地址为
Sentinel 的作用
在上面简介中也说了,Sentinel 是微服务时代保障稳定的神兵利器
举个例子:电商系统中用户浏览商品详情页,通常会通过 RPC 调用多个微服务,查询商品信息的同时还会查询用户的信息,也会展示优惠信息,通常下拉列表还会展示推荐,广告等信息,如下图
如果流量较大时,CouponService 容量不足,或者某种原因导致 RecomService 不可用,此时 AggrService 会被拖死,导致商品详情服务不可用,但仔细想想这些服务不是那么重要,可以进行限流或者直接降级(不再调用),总比直接服务不用要好吧
又或者流量实在太高,ProductService 也顶不住了,那是否可以采取限流措施,保住部分用户的请求时正常的,也比全部不可用要好
这些问题,Sentinel 都能解决
Sentinel 提供的能力
Sentinel 将要保护的对象(可以是某个服务或一段代码)抽象为资源,通过动态下发的规则,对资源进行
- 流量控制
- 熔断降级
针对这两个主要功能又有很多的玩法,比如限流是针对QPS还是并发数,控制的效果是直接拒绝还是排队等等。
当然 Sentinel 也提供一个开箱即用的 Dashboard,可扩展配中心进行下发规则,展示监控指标,调用关系链等等
快速开始
源码阅读环境准备
- fork 源码到自己仓库,便于增加注释
- 拉取源码到本地
git clone git@github.com:lkxiaolou/sentinel-golang.git
- 导入 IDE,由于我既要写 Java 又要写 Go,所以用 IntelliJ IDEA 比较方便,只要装一个 Go plugin 就可以了
- 导入后,一般 IDE 会自动下载依赖,如果没有自动下载,试试执行( Go 安装就不说了)
go mod download
目录结构介绍
- sentinel-golang
- api:对外暴露的接口
- core:核心实现
- example:使用例子
- exporter:Prometheus的exporter
- ext:扩展接口,主要是动态规则配置中心扩展接口
- logging:日志模块
- pkg:第三方插件的实现,比如各个组件适用 Sentinel 的 adapter,以及 Sentinel 对接各种第三方配置中心的扩展实现
- tests:测试类代码,包括单元测试、benchmark
- util:工具类
样例跑通
在 /example 目录下新建 mytests 目录,并创建一个 quick_start.go 文件,按照官网给出的例子,先用最简单的默认方式初始化
if err := sentinel.InitDefault(); err != nil {
// 初始化失败
panic(err.Error())
}
再用写死的方式加载规则
// 资源名
resource := "test-resource"
// 加载流控规则,写死
_, err := flow.LoadRules([]*flow.Rule{
{
Resource: resource,
// Threshold + StatIntervalInMs 可组合出多长时间限制通过多少请求,这里相当于限制为 10 qps
Threshold: 10,
StatIntervalInMs: 1000,
// 暂时不用关注这些参数
TokenCalculateStrategy: flow.Direct,
ControlBehavior: flow.Reject,
},
})
最后写测试代码
// 修改这个看看效果吧
currency := 100
for i := 0; i < currency; i++ {
go func() {
e, b := sentinel.Entry(resource, sentinel.WithTrafficType(base.Inbound))
if b != nil {
// 被流控
fmt.Printf("blocked %s \n", b.BlockMsg())
} else {
// 通过
fmt.Println("pass...")
// 通过后必须调用Exit
e.Exit()
}
}()
}
这里限制了 10 qps,我们用 100 个协程并发测试跑一下,刚好通过10个请求
测试代码已上传到我的仓库
https://github.com/lkxiaolou/sentinel-golang/tree/master/example/mytests
总结
本文介绍了 Sentinel 的和它能解决的问题,以及源码阅读的一些准备工作,并跑通了一个最简单的例子,见识到了 Sentinel 限流的效果,本文先到这里,我们下一节见。
搜索关注微信公众号"捉虫大师",后端技术分享,架构设计、性能优化、源码阅读、问题排查、踩坑实践。
Sentinel-Go 源码系列(一)|开篇的更多相关文章
- 深入学习JDK源码系列之、ArrayList
前言 JDK源码解析系列文章,都是基于JDK8分析的,虽然JDK15马上要出来了,但是JDK8我还不会,我... 类图 实现了RandomAccess接口,可以随机访问 实现了Cloneable接口, ...
- 事件机制-Spring 源码系列(4)
事件机制-Spring 源码系列(4) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostProcess ...
- Ioc容器依赖注入-Spring 源码系列(2)
Ioc容器依赖注入-Spring 源码系列(2) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostPr ...
- Ioc容器BeanPostProcessor-Spring 源码系列(3)
Ioc容器BeanPostProcessor-Spring 源码系列(3) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Io ...
- AOP执行增强-Spring 源码系列(5)
AOP增强实现-Spring 源码系列(5) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostProc ...
- 大白话Vue源码系列(02):编译器初探
阅读目录 编译器代码藏在哪 Vue.prototype.$mount 构建 AST 的一般过程 Vue 构建的 AST 题接上文,上回书说到,Vue 的编译器模块相对独立且简单,那咱们就从这块入手,先 ...
- 大白话Vue源码系列(03):生成AST
阅读目录 AST 节点定义 标签的正则匹配 解析用到的工具方法 解析开始标签 解析结束标签 解析文本 解析整块 HTML 模板 未提及的细节 本篇探讨 Vue 根据 html 模板片段构建出 AST ...
- 大白话Vue源码系列(03):生成render函数
阅读目录 优化 AST 生成 render 函数 小结 本来以为 Vue 的编译器模块比较好欺负,结果发现并没有那么简单.每一种语法指令都要考虑到,处理起来相当复杂.上篇已经生成了 AST,本篇依然对 ...
- 大白话Vue源码系列(04):生成render函数
阅读目录 优化 AST 生成 render 函数 小结 本来以为 Vue 的编译器模块比较好欺负,结果发现并没有那么简单.每一种语法指令都要考虑到,处理起来相当复杂.上篇已经生成了 AST,本篇依然对 ...
- 大白话Vue源码系列(05):运行时鸟瞰图
阅读目录 Vue 实例的生命周期 实例创建 响应的数据绑定 挂载到 DOM 节点 结论 研究 runtime 一边 Vue 一边源码 初看 Vue 是 Vue 源码是源码 再看 Vue 不是 Vue ...
随机推荐
- 将 VS2017下开发的程序, 部署到其他电脑上运行
关键步骤:设置Release,如下图 如果无法直接执行,则安装ALI213-Microsoft.Visual.C++.2017.Redistributable.Package.x86.x64
- 剑指 Offer 34. 二叉树中和为某一值的路径
剑指 Offer 34. 二叉树中和为某一值的路径 输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径.从树的根节点开始往下一直到叶节点所经过的节点形成一条路径. 示例: 给定如下 ...
- Java创建线程池的方法
Executors创建四种线程池: CachedThreadPool:可缓存的线程池,该线程池中没有核心线程,非核心线程的数量为Integer.max_value,当有需要时创建线程来执行任务,没有需 ...
- awk 命令-随笔
awk语法: awk [option] 'pattern{action}' file ... awk [参数] '条件{动作}' 文件 ... 解析: 命令: awk 参数: -F "&qu ...
- Linux/CentOS基础命令1
一.系统相关运行命令1.系统关机命令:shutdown# shutdown 关机 Shutdown scheduled for Fri 2019-03-29 11:36:45 CST, use 'sh ...
- 痞子衡嵌入式:MCUXpresso IDE下将应用程序RW段分散链接的几种方法
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MCUXpresso IDE下将应用程序RW段分散链接的几种方法. 早期的 MCU 芯片,一般都会嵌入内部 Flash 和 RAM,并且 ...
- expression select表达式动态构建
参考: http://blog.csdn.net/tastelife/article/details/7340205 http://blog.csdn.net/sweety820/article/de ...
- 羽夏看Win系统内核——简述
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...
- 洛谷P1019——单词接龙(DFS暴力搜索)
https://www.luogu.org/problem/show?pid=1019#sub 题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母, ...
- PHP中操作任意精度大小的GMP扩展学习
对于各类开发语言来说,整数都有一个最大的位数,如果超过位数就无法显示或者操作了.其实,这也是一种精度越界之后产生的精度丢失问题.在我们的 PHP 代码中,最大的整数非常大,我们可以通过 PHP_INT ...