![ee886ad0383cc458edb9ecd337ecb549.png](https://i-blog.csdnimg.cn/blog_migrate/d37f56ea3972e02327c57d4de34978c0.jpeg)
写在前面
在互联网应用中,高并发系统会面临一个重大的挑战,那就是大量流高并发访问,比如:天猫的双十一、京东618、秒杀、抢购促销等,这些都是典型的大流量高并发场景。关于秒杀,小伙伴们可以参见我的另一篇文章《【高并发】高并发秒杀系统架构解密,不是所有的秒杀都是秒杀!》
关于【冰河技术】微信公众号,解锁更多【高并发】专题文章。
注意:由于原文篇幅比较长,所以被拆分为:理论、算法、实战(HTTP接口实战+分布式限流实战)三大部分。
理论篇:《【高并发】如何实现亿级流量下的分布式限流?这些理论你必须掌握!!》
算法篇:《【高并发】如何实现亿级流量下的分布式限流?这些算法你必须掌握!!》
项目源码已提交到github: https:// github.com/sunshinelyz/ mykit-ratelimiter
HTTP接口限流实战
这里,我们实现Web接口限流,具体方式为:使用自定义注解封装基于令牌桶限流算法实现接口限流。
不使用注解实现接口限流
搭建项目
这里,我们使用SpringBoot项目来搭建Http接口限流项目,SpringBoot项目本质上还是一个Maven项目。所以,小伙伴们可以直接创建一个Maven项目,我这里的项目名称为mykit-ratelimiter-test。接下来,在pom.xml文件中添加如下依赖使项目构建为一个SpringBoot项目。
<parent>
可以看到,我在项目中除了引用了SpringBoot相关的Jar包外,还引用了guava框架,版本为28.2-jre。
创建核心类
这里,我主要是模拟一个支付接口的限流场景。首先,我们定义一个PayService接口和MessageService接口。PayService接口主要用于模拟后续的支付业务,MessageService接口模拟发送消息。接口的定义分别如下所示。
- PayService
package
- MessageService
package
接下来,创建二者的实现类,分别如下。
- MessageServiceImpl
package
- PayServiceImpl
package
由于是模拟支付和发送消息,所以,我在具体实现的方法中打印出了相关的日志,并没有实现具体的业务逻辑。
接下来,就是创建我们的Controller类PayController,在PayController类的接口pay()方法中使用了限流,每秒钟向桶中放入2个令牌,并且客户端从桶中获取令牌,如果在500毫秒内没有获取到令牌的话,我们可以则直接走服务降级处理。
PayController的代码如下所示。
package
最后,我们来创建mykit-ratelimiter-test项目的核心启动类,如下所示。
package
至此,我们不使用注解方式实现限流的Web应用就基本完成了。
运行项目
项目创建完成后,我们来运行项目,运行SpringBoot项目比较简单,直接运行MykitLimiterApplication类的main()方法即可。
项目运行成功后,我们在浏览器地址栏输入链接:http://localhost:8080/boot/pay。页面会输出“支付成功”的字样,说明项目搭建成功了。如下所示。
![1d73b85540c78159f7f276f5af7fdc13.png](https://i-blog.csdnimg.cn/blog_migrate/66290ea6c8401178e89713531635d049.png)
此时,我只访问了一次,并没有触发限流。接下来,我们不停的刷浏览器,此时,浏览器会输出“支付失败,再试一次吧...”的字样,如下所示。
![a8a18bbfb217e790c8371fba1ab6d936.png](https://i-blog.csdnimg.cn/blog_migrate/806a0d6f5c3bfdaa04195d6fcee39953.png)
在PayController类中还有一个sendMessage()方法,模拟的是发送消息的接口,同样使用了限流操作,具体代码如下所示。
@RequestMapping
sendMessage()方法的代码逻辑和运行效果与pay()方法相同,我就不再浏览器访问 http://localhost:8080/boot/send/message 地址的访问效果了,小伙伴们可以自行验证。
不使用注解实现限流缺点
通过对项目的编写,我们可以发现,当在项目中对接口进行限流时,不使用注解进行开发,会导致代码出现大量冗余,每个方法中几乎都要写一段相同的限流逻辑,代码十分冗余。
如何解决代码冗余的问题呢?我们可以使用自定义注解进行实现。
使用注解实现接口限流
使用自定义注解,我们可以将一些通用的业务逻辑封装到注解的切面中,在需要添加注解业务逻辑的方法上加上相应的注解即可。针对我们这个限流的实例来说,可以基于自定义注解实现。
实现自定义注解
实现,我们来创建一个自定义注解,如下所示。
package
自定义注解切面实现
接下来,我们还要实现一个切面类MyRateLimiterAspect,如下所示。
package
自定义切面的功能比较简单,我就不细说了,大家有啥问题可以关注【冰河技术】微信公众号来进行提问。
接下来,我们改造下PayController类中的sendMessage()方法,修改后的方法片段代码如下所示。
@MyRateLimiter
运行部署项目
部署项目比较简单,只需要运行MykitLimiterApplication类下的main()方法即可。这里,为了简单,我们还是从浏览器中直接输入链接地址来进行访问
效果如下所示。
![5cc88622d029ed93e9fa4cd16dd2c71c.png](https://i-blog.csdnimg.cn/blog_migrate/a242a12886fcaf1388db54a2af60807e.png)
接下来,我们不断的刷新浏览器。会出现“消息发送失败,再试一次吧..”的字样,说明已经触发限流操作。
![977046e2aa30a068f2454ff6f14f4f49.png](https://i-blog.csdnimg.cn/blog_migrate/afda789a42768538c104c71d932a8d89.png)
基于限流算法实现限流的缺点
上面介绍的限流方式都只能用于单机部署的环境中,如果将应用部署到多台服务器进行分布式、集群,则上面限流的方式就不适用了,此时,我们需要使用分布式限流。至于在分布式场景下,如何实现限流操作,我们就在下一篇中进行介绍。
重磅福利
关注「 冰河技术 」微信公众号,后台回复 “设计模式” 关键字领取《深入浅出Java 23种设计模式》PDF文档。回复“Java8”关键字领取《Java8新特性教程》PDF文档。两本PDF均是由冰河原创并整理的超硬核教程,面试必备!!
好了,今天就聊到这儿吧!别忘了点个赞,给个在看和转发,让更多的人看到,一起学习,一起进步!!
写在最后
如果你觉得冰河写的还不错,请微信搜索并关注「 冰河技术 」微信公众号,跟冰河学习高并发、分布式、微服务、大数据、互联网和云原生技术,「 冰河技术 」微信公众号更新了大量技术专题,每一篇技术文章干货满满!不少读者已经通过阅读「 冰河技术 」微信公众号文章,吊打面试官,成功跳槽到大厂;也有不少读者实现了技术上的飞跃,成为公司的技术骨干!如果你也想像他们一样提升自己的能力,实现技术能力的飞跃,进大厂,升职加薪,那就关注「 冰河技术 」微信公众号吧,每天更新超硬核技术干货,让你对如何提升技术能力不再迷茫!
http://weixin.qq.com/r/dB10bAHE0FyvrUUP90hm (二维码自动识别)