1 前言
网上大多源码解析教程大多都是一开始就直接深入源码, 一步一步讲解, 也算是一种方法, 但在我看来不可避免的会“一叶障目” 专注于太小的一个点,反而会忘了本来目的, 本文就从另一个角度解读sentinel源码,能真正的从“全局角度”理解sentinel, 当然这种方法你可以用在任何地方, 废话不多说我们开始.
2 思考
2.1 从功能思考
首先我们从最先开始, 如果从0开始实现一个最简单的限流,你会怎么实现? 很容易想到, 其实就是设计一定的条件, 比如1s内允许通过100qps请求, 程序很简单, 可以用粗暴的达到100直接限制, 或者业界通用令牌桶, 或者匀速算法 对应到sentinel 即是default, warmUp, RateLimiter.
接着我们会想到直接写限流规则肯定是最粗暴的做法, 所以需要抽象, 怎么抽象? 具体规则抽象成类, 还需要一个具体管理规则类,方便后面管理扩展, 这里对应sentinel 的 FlowRuleManager FlowRule
限流数据哪里来? 肯定不会是直接写死, 所以这里需要抽象另一个类用于收集数据这里对应sentinel 的 StatisticRule StatisticManager
从什么维度限流数据? 自定义string 和 通用methodName 对应的就是 sentinel StringResourceWrapper和MethodResourceWrapper
现在我们有了一个最基本限流的框架, 通过StringResourceWrapper 或者MethodResourceWrapper维度限流, 规则通过FlowRuleManager来 数据通过StatisticManager来 但是这样肯定远远不够
2.2 从可维护性扩展角度思考
接着我们从可维护性和扩展性的角度,解读sentinel 设计思想
数据是有了, 但是你不可能只有一段代码,只有一个限流规则, 所以需要一个统一存储的地方存储这些统计数据, 这就是ClusterBuilderSlot
前面我们已经有了FlowRuleManager 用来管理我们的规则, 但是没有一个配置更新的地方, 所以sentinel提供了ZooKeeper, Redis, Nacos, Apollo, etcd 这些扩展点
这里用了观察者模式通知对应关心的配置下发
提供了两种pull和push模式用于配置更新
接着思考, 我们如果一条链路里全部处理收集数据 存储数据, 存储规则, check规则, 是不是太重了? 需要抽象设计把这些逻辑分开, 那么那种设计模式最好? 这里sentinel用了责任链模式, 也很好理解,各个规则全部需要处理, 也要考虑到以后扩展, 设计成责任链模式可以说是完美适合的场景
责任链模式把这些规则串起来了, 那这里是不是还少了一个重要的东西? 数据之间如何互通? 这里就要引入上下文 context 串联这些数据
经过上面这些我们脑子里应该对sentinel这个开源框架有了整体的了解, 并且知道了为什么这么设计.
在此之后去阅读其他sentinel 源码理解的文章应该会事半功倍了.
3 结语
从全局角度思考源码的设计方式,接着在脑子里形成一个相对的概念, 这方法不仅在阅读源码游泳,在自己设计也有用, 等到脑子里有完整的想法了, 代码也只不过是对应填充进去而已.












网友评论