Java服务_使用Guava缓存实现服务限流
1.Guava Cache原理
guava cache就是单个应用运行时保存在本地内存中的缓存,是单机版的。本质与concurrentmap相似,但是concurrentmap只能显式地remove数据,guava cache提供了很多自动回收机制。guava cache常用于服务限流。
guava cache适用于小量被读取频繁的数据,本质是以空间换时间,牺牲内存提高读取速度。
guava cache的优点:
- 线程安全,与concurrentmap类似。
- 提供了三种基本回收方式:基于容量回收、定时回收、基于引用回收。其中基于容量回收采用LRU策略。
- 监控缓存加载和命中情况。
- 集成了多部操作,支持在未命中缓存时,从其他数据源(mysql、redis)获取数据。
2.服务限流实例
2.1创建SpringBoot项目和依赖
创建maven项目,添加pom.xml依赖
1 |
|
创建application类
1 | package jia.zheng; |
2.2创建限流器
限流逻辑主要在dolimit方法中
1 | package jia.zheng.limiter.impl; |
- maximumSize()方法用于设置guava cache的最大容量为100个entry,超过则会按照LRU策略回收。guava cache还提供了很多缓存配置和操作方法,如定时回收、显式清除、设置监听器等。
- CacheLoader中的load()方法为cache未命中时从别处加载value的逻辑,还会自动将该value存入cache中。可以将此处逻辑改为从mysql或远程redis中获取,从而真正地将guava cache作为数据缓存使用。
- 限流一般要设置在timeLimit时间内限定访问countLimit次这两个参数,此处为了展示方便直接在代码中写死。常见策略为将该参数保存在redis中,然后使用定时轮询任务轮询获取该参数保存在static修饰的map中,然后本方法直接从该map中拿。因为限流本来就是很重视时效性,所以尽量避免本方法直接从远程redis或mysql中获取限流参数。
2.3创建工具类实现单例模式
要使用单例模式确保项目中只有一个LimiterImpl类对象在工作,使用饿汉模式或饱汉模式都可以。
spring项目中也可以直接在LimiterImpl类上添加@Component注解,借助spring实现单例bean。
1 | package jia.zheng.limiter; |
- 类的加载是私有的,别的线程无法进入。所以不用担心两个命令同时加载limitUtil类导致静态代码块执行两次。
2.4创建Controller
1 | package jia.zheng.controller; |
2.5启动该SpringBoot项目并连续访问
连续访问3次,浏览器显示都是访问成功:

连续访问第4次及以后都是访问失败:

过了30s之后再连续访问则又能成功3次。