PS: Lua脚本放置在classpath下,通过ClassPathResource进行加载 。
这里我们定义了一个切点,表示只要注解了@RateLimiter 的方法,均可以触发限流操作 。
这段代码的逻辑为,获取 @RateLimiter 注解配置的属性:key、limit、expire,并通过redisTemplate.execute(RedisScriptscript,Listkeys,Object…args) 方法传递给Lua脚本进行限流相关操作,逻辑很清晰 。
这里我们定义如果脚本返回状态为0则为触发限流,1表示正常请求 。
5. Lua脚本
这里是我们整个限流操作的核心,通过执行一个Lua脚本进行限流的操作 。脚本内容如下
逻辑很通俗,我简单介绍下 。
1、首先脚本获取Java代码中传递而来的要限流的模块的key,不同的模块key值一定不能相同,否则会覆盖!2、redis.call(‘incr’, key1)对传入的key做incr操作,如果key首次生成,设置超时时间ARGV[1];(初始值为1) 3、ttl是为防止某些key在未设置超时时间并长时间已经存在的情况下做的保护的判断;4、每次请求都会做+1操作,当限流的值val大于我们注解的阈值,则返回0表示已经超过请求限制,触发限流 。否则为正常请求 。
当过期后,又是新的一轮循环,整个过程是一个原子性的操作,能够保证单位时间不会超过我们预设的请求阈值 。
到这里我们便可以在项目中进行测试 。
测试
这里我贴一下核心代码,我们定义一个接口,并注解@RateLimiter(key=“ratedemo:1.0.0”,limit=5,expire=100) 表示模块ratedemo:sendPayment:1.0.0 在100s内允许通过5个请求,这里的参数设置是为了方便看结果 。实际中,我们通常会设置1s内允许通过的次数 。
我们通过RestClient请求接口,日志返回如下:
根据日志能够看到,正常请求5次后,返回限流触发,说明我们的逻辑生效,对前端而言也是可以看到false标记,表明我们的Lua脚本限流逻辑是正确的,这里具体返回什么标记需要调用方进行明确的定义 。
总结
我们通过Redis的incr及expire功能特性,开发定义了一套基于注解的分布式限流操作,核心逻辑基于Lua保证了原子性 。达到了很好的限流的目的,生产上,可以基于该特点进行定制自己的限流组件,当然你可以参考本文的代码,相信你写的一定比我的demo更好!
推荐阅读
- 沈抖详解百度小程序背后逻辑:做了小程序以后,即使大家再来骂我,我认了
- 百度SEO和谷歌SEO的区别有哪些?
- 2022年百度集卡一个人几个账号可以同时参加吗,2022年百度集卡活动一人只能参与一次吗
- 如何成为一名风水师 风水师养成记
- 鸡精和味精哪个对健康有危害?很多人都想错了,营养师给你讲清楚
- 茶与茶文化着眼于培养中级茶艺师的基本技能
- 洗发水|女人年纪大了,长发和短发哪个更适合?美发师:发质和发量说了算
- 满级绿茶在年代文躺赢_by云吉锦绣_txt全文阅读,百度网盘免费下载[绿茶]
- 镇江实验高中老师在线看 想看镇江实验中学视频
- B/S架构及其运行原理