设计模式之美
王争
前 Google 工程师,《数据结构与算法之美》专栏作者
123426 人已学习
新⼈⾸单¥98
登录后,你可以任选6讲全文学习
课程目录
已完结/共 113 讲
设计模式与范式:行为型 (18讲)
设计模式之美
15
15
1.0x
00:00/00:00
登录|注册

92 | 项目实战一:设计实现一个支持各种算法的限流框架(实现)

可测试性
复用性
简洁
灵活
可维护性
扩展性
可读性
借鉴Spring的设计思路
支持自定义限流规则配置文件名和路径
重构修改和优化
针对MVP代码的问题
从代码质量评判标准的角度
结合SOLID、DRY、KISS、LOD、基于接口而非实现编程、高内聚松耦合等经典的设计思想和原则
课堂讨论
站在Code Reviewer的角度
追求完美主义会让我们迟迟无法下手
小步快跑、逐步迭代
如何对MVP代码优化重构
优秀的代码是重构出来的
实现篇:设计实现一个支持各种算法的限流框架

该思维导图由 AI 生成,仅供参考

上一节课,我们介绍了如何通过合理的设计,来实现功能性需求的同时,满足易用、易扩展、灵活、低延迟、高容错等非功能性需求。在设计的过程中,我们也借鉴了之前讲过的一些开源项目的设计思想。比如,我们借鉴了 Spring 的低侵入松耦合、约定优于配置等设计思想,还借鉴了 MyBatis 通过 MyBatis-Spring 类库将框架的易用性做到极致等设计思路。
今天,我们讲解这样一个问题,针对限流框架的开发,如何做高质量的代码实现。说的具体点就是,如何利用之前讲过的设计思想、原则、模式、编码规范、重构技巧等,写出易读、易扩展、易维护、灵活、简洁、可复用、易测试的代码。
话不多少,让我们正式开始今天的学习吧!

V1 版本功能需求

我们前面提到,优秀的代码是重构出来的,复杂的代码是慢慢堆砌出来的。小步快跑、逐步迭代是我比较推崇的开发模式。所以,针对限流框架,我们也不用想一下子就做得大而全。况且,在专栏有限的篇幅内,我们也不可能将一个大而全的代码阐述清楚。所以,我们可以先实现一个包含核心功能、基本功能的 V1 版本。
针对上两节课中给出的需求和设计,我们重新梳理一下,看看有哪些功能要放到 V1 版本中实现。
在 V1 版本中,对于接口类型,我们只支持 HTTP 接口(也就 URL)的限流,暂时不支持 RPC 等其他类型的接口限流。对于限流规则,我们只支持本地文件配置,配置文件格式只支持 YAML。对于限流算法,我们只支持固定时间窗口算法。对于限流模式,我们只支持单机限流。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

设计实现一个支持各种算法的限流框架是一项复杂而重要的任务。本文深入探讨了如何借鉴开源项目的设计思想,详细讲解了V1版本的功能需求,并展示了最小原型代码的目录结构和相关类的代码实现。重点剖析了代码的设计和实现,从可读性和扩展性两个方面进行了评估,并提出了重构建议。通过对MVP代码的重构,拆分出了限流规则加载的逻辑,并设计了抽象接口,以提高代码的扩展性。总结强调了优秀代码是通过重构得到的,鼓励采用小步快跑、逐步迭代的开发模式。读者可以从中学习到如何优化重构MVP代码,以及如何评估代码质量并针对性地进行优化。文章提出了课堂讨论问题,引发读者思考如何进行code review和重构,以及如何支持自定义限流规则配置文件名和路径。欢迎读者分享自己的想法,并将这篇文章分享给更多朋友,共同学习成长。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《设计模式之美》
新⼈⾸单¥98
立即购买
登录 后留言

全部留言(31)

  • 最新
  • 精选
  • Jie
    https://github.com/wangzheng0822/ratelimiter4j 老师忘记在专栏里面放自己项目的地址了么,翻看隔壁算法之美发现的

    作者回复: 感谢你的补充!

    2020-06-05
    3
    18
  • 高源
    老师今天讲的骨架,有代码吗,我想结合你讲的自己再多考虑和分析,学习其中的方法解决的问题

    作者回复: 代码都在文章里了,你也可以看下我github上的一个比较老的版本的,但写的比较详细 https://github.com/wangzheng0822

    2020-06-03
    7
  • 杨杰
    1、在配置文件中是否应该指定默认的限流算法和每个api(或appid)对应的算法,在加载配置文件的时候自动生成这个配置算法的实例 2、在RateLimiter中的limit方法里面添加每个api对应的限流算法这个地方感觉有点儿不太好,如果每个API对应的限流算法都不一样会导致大量的If else 判断,是不是应该像第一点说的那样初始化的时候就自动生成了。

    作者回复: 可以把选择哪种限流算法配置到配置文件中,但没有必要给每个appid都配置不同的限流算法吧

    2020-06-18
    3
  • 沧海
    public class RuleConfig { private List<UniformRuleConfig> configs; public List<AppRuleConfig> getConfigs() { return configs; } } RuleConfig中的属性configs类型应该是List<AppRuleConfig>

    作者回复: 嗯呢,多谢指出!

    2020-06-10
    1
  • HuaMax
    stopwatch.reset()之后要调用stopwatch.start()重新开始,或者stopwatch.stop().start(),亲入坑。。。
    2020-06-03
    25
  • jaryoung
    课后习题二: 如何重构代码,支持自定义限流规则配置文件名和路径? public static final String DEFAULT_API_LIMIT_CONFIG_NAME = "ratelimiter-rule"; private final String customApiLimitConfigPath; public FileRuleConfigSource(String configLocation) { this.customApiLimitConfigPath = configLocation; } private String getFileNameByExt(String extension) { return StringUtils.isEmpty(customApiLimitConfigPath) ? DEFAULT_API_LIMIT_CONFIG_NAME + "." + extension : customApiLimitConfigPath; } Spring boot 如何实现配置文件约定和扫描?可以去看看ConfigFileApplicationListener 这个类,如何跑起来,请去debug,不懂怎么debug,请新建窗口输入 google.com
    2020-06-03
    12
  • leezer
    RatelimitAlg在重构后应该是可支持多种算法形式,那么在limit调用的时候应该不是直接new出来,可以通过策略形式进行配置,而算法的选取应该包含默认和指定,也可以配置到文件规则里面。
    2020-06-03
    5
  • bucher
    感谢争哥,写的很棒。根据url查找限流规则使用了trie树这块是不是属于过度设计呢?一个app下的api个数不多的情况,直接用map存就可以了吧(map的key使用url名)
    2021-01-04
    2
    3
  • djfhchdh
    1、RateLimiter类中,构建api对应在内存中的限流计数器(RateLimitAlg)这个逻辑可以独立出来,初始化的过程中,就将api和相应RateLimitAlg实现类的对应关系建立好; 2、可以使用DI框架,FileRuleConfigSource构建时,从bean配置文件读取构造参数,如果没有提供构造参数就用默认值
    2020-06-04
    3
  • 龙猫
    tryAcquire 为什么要 调用两次 currentCount.incrementAndGet()方法呢?没太看懂,有大佬解释一下吗
    2020-10-01
    3
    2
收起评论
显示
设置
留言
31
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部