}
//同步阻塞限流
@GetMapping(“/acquire”)
public String acquire(Integer count){
limiter.acquire(count);
log.info(“成功,允许通过,速率为{}”,limiter.getRate());
return “success”;
}
}
2)基于Nginx的限流
============
1.iP限流
1.编写Controller
@RestController
@Slf4j
public class Controller{
//nginx测试使用
@GetMapping(“/nginx”)
public String nginx(){
log.info(“Nginx success”);
}
}
2.修改host文件,添加一个网址域名
127.0.0.1 www.test.com
3.修改nginx,将步骤2中的域名,添加到路由规则当中
打开nginx的配置文件
vim /usr/local/nginx/conf/nginx.conf
添加一个服务
#根据IP地址限制速度
#1)$binary_remote_addr binary_目的是缩写内存占用,remote_addr表示通过IP地址来限流
#2)zone=iplimit:20m iplimit是一块内存区域(记录访问频率信息),20m是指这块内存区域的大小
#3)rate=1r/s 每秒放行1个请求
limit_req_zone $binary_remote_addr zone=iplimit:20m rate=1r/s;
server{
server_name www.test.com;
location /access-limit/ {
proxy_pass http://127.0.0.1:8080/;
#基于ip地址的限制
#1)zone=iplimit 引用limit_rep_zone中的zone变量
#2)burst=2 设置一个大小为2的缓冲区域,当大量请求到来,请求数量超过限流频率时,将其放入缓冲区域
#3)nodelay 缓冲区满了以后,直接返回503异常
limit_req zone=iplimit burst=2 nodelay;
}
}
4.访问地址,测试是否限流
www.test.com/access-limit/nginx
2.多维度限流
1.修改nginx配置
#根据IP地址限制速度
limit_req_zone $binary_remote_addr zone=iplimit:20m rate=10r/s;
#根据服务器级别做限流
limit_req_zone $server_name zone=serverlimit:10m rate=1r/s;
#根据ip地址的链接数量做限流
limit_conn_zone $binary_remote_addr zone=perip:20m;
#根据服务器的连接数做限流
limit_conn_zone $server_name zone=perserver:20m;
server{
server_name www.test.com;
location /access-limit/ {
proxy_pass http://127.0.0.1:8080/;
#基于ip地址的限制
limit_req zone=iplimit burst=2 nodelay;
#基于服务器级别做限流
limit_req zone=serverlimit burst=2 nodelay;
#基于ip地址的链接数量做限流 最多保持100个链接
limit_conn zone=perip 100;
#基于服务器的连接数做限流 最多保持100个链接
limit_conn zone=perserver 1;
#配置request的异常返回504(默认为503)
limit_req_status 504;
limit_conn_status 504;
}
location /download/ {
#前100m不限制速度
limit_rate_affer 100m;
#限制速度为256k
limit_rate 256k;
}
}
3)基于Redis+Lua的分布式限流
===================
1.Lua脚本
Lua是一个很小巧精致的语言,它的诞生(1993年)甚至比JDK 1.0还要早。Lua是由标准的C语言编写的,它的源码部分不过2万多行C代码,甚至一个完整的Lua解释器也就200k的大小。
Lua往大了说是一个新的编程语言,往小了说就是一个脚本语言。对于有编程经验的同学,拿到一个Lua脚本大体上就能把业务逻辑猜的八九不离十了。
Redis内置了Lua解释器,执行过程保证原子性
2.Lua安装
安装Lua:
1.参考http://www.lua.org/ftp/教程,下载5.3.5_1版本,本地安装
如果你使用的是Mac,那建议用brew工具直接执行brew install lua就可以顺利安装,有关brew工具的安装可以参考https://brew.sh/网站,使用brew安装后的目录在/usr/local/Cellar/lua/5.3.5_1
2.安装IDEA插件,在IDEA->Preferences面板,Plugins,里面Browse repositories,在里面搜索lua,然后就选择同名插件lua。安装好后重启IDEA
3.配置Lua SDK的位置:IDEA->File->Project Structure,选择添加Lua,路径指向Lua SDK的bin文件夹
4.都配置好之后,在项目中右键创建Module,左侧栏选择lua,点下一步,选择lua的sdk,下一步,输入lua项目名,完成
3.编写hello lua
print ‘Hello Lua’
4.编写模拟限流
– 模拟限流
– 用作限流的key
local key = ‘my key’
– 限流的最大阈值
local limit = 2
– 当前限流大小
local currentLimit = 2
– 是否超过限流标准
if currentLimit + 1 > limit then
print ‘reject’
return false
else
print ‘accept’
return true
end
5.限流组件封装
1.添加maven
org.springframework.boot
spring-boot-starter-data-redis
org.springframework.boot
spring-boot-starter-aop
com.google.guava
guava
18.0
2.添加Spring配置
不是重要内容就随便写点,主要就是把reids配置一下
server.port=8080
spring.redis.database=0
spring.redis.host=localhost
spring.redis.port=6376
3.编写限流脚本
lua脚本放在resource目录下就可以了
– 获取方法签名特征
local methodKey = KEYS[1]
redis.log(redis.LOG_DEBUG,‘key is’,methodKey)
– 调用脚本传入的限流大小
local limit = tonumber(ARGV[1])
– 获取当前流量大小
local count = tonumber(redis.call(‘get’,methodKey) or “0”)
–是否超出限流值
if count + 1 >limit then
– 拒绝访问
return false
else
– 没有超过阈值
– 设置当前访问数量+1
redis.call(‘INCRBY’,methodKey,1)
– 设置过期时间
redis.call(‘EXPIRE’,methodKey,1)
– 放行
return true
end
4.使用spring-data-redis组件集成Lua和Redis
创建限流类
@Service
@Slf4j
public class AccessLimiter{
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private RedisScript rateLimitLua;
public void limitAccess(String key,Integer limit){
boolean acquired = stringRedisTemplate.execute(
rateLimitLua,//lua脚本的真身
Lists.newArrayList(key),//lua脚本中的key列表
limit.toString()//lua脚本的value列表
);
if(!acquired){
log.error(“Your access is blocked,key={}”,key);
throw new RuntimeException(“Your access is blocked”);
}
}
}
创建配置类
@Configuration
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
![img](https://i-blog.csdnimg.cn/blog_migrate/4772f873ade6ea18e015320603cb82dc.jpeg)
最后
ActiveMQ消息中间件面试专题
- 什么是ActiveMQ?
- ActiveMQ服务器宕机怎么办?
- 丢消息怎么办?
- 持久化消息非常慢怎么办?
- 消息的不均匀消费怎么办?
- 死信队列怎么办?
- ActiveMQ中的消息重发时间间隔和重发次数吗?
ActiveMQ消息中间件面试专题解析拓展:
redis面试专题及答案
- 支持一致性哈希的客户端有哪些?
- Redis与其他key-value存储有什么不同?
- Redis的内存占用情况怎么样?
- 都有哪些办法可以降低Redis的内存使用情况呢?
- 查看Redis使用情况及状态信息用什么命令?
- Redis的内存用完了会发生什么?
- Redis是单线程的,如何提高多核CPU的利用率?
Spring面试专题及答案
- 谈谈你对 Spring 的理解
- Spring 有哪些优点?
- Spring 中的设计模式
- 怎样开启注解装配以及常用注解
- 简单介绍下 Spring bean 的生命周期
Spring面试答案解析拓展
高并发多线程面试专题
- 现在有线程 T1、T2 和 T3。你如何确保 T2 线程在 T1 之后执行,并且 T3 线程在 T2 之后执行?
- Java 中新的 Lock 接口相对于同步代码块(synchronized block)有什么优势?如果让你实现一个高性能缓存,支持并发读取和单一写入,你如何保证数据完整性。
- Java 中 wait 和 sleep 方法有什么区别?
- 如何在 Java 中实现一个阻塞队列?
- 如何在 Java 中编写代码解决生产者消费者问题?
- 写一段死锁代码。你在 Java 中如何解决死锁?
高并发多线程面试解析与拓展
jvm面试专题与解析
- JVM 由哪些部分组成?
- JVM 内存划分?
- Java 的内存模型?
- 引用的分类?
- GC什么时候开始?
JVM面试专题解析与拓展!
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门即可获取!
0)]
高并发多线程面试专题
- 现在有线程 T1、T2 和 T3。你如何确保 T2 线程在 T1 之后执行,并且 T3 线程在 T2 之后执行?
- Java 中新的 Lock 接口相对于同步代码块(synchronized block)有什么优势?如果让你实现一个高性能缓存,支持并发读取和单一写入,你如何保证数据完整性。
- Java 中 wait 和 sleep 方法有什么区别?
- 如何在 Java 中实现一个阻塞队列?
- 如何在 Java 中编写代码解决生产者消费者问题?
- 写一段死锁代码。你在 Java 中如何解决死锁?
高并发多线程面试解析与拓展
[外链图片转存中…(img-4Ps90kDB-1711894252790)]
jvm面试专题与解析
- JVM 由哪些部分组成?
- JVM 内存划分?
- Java 的内存模型?
- 引用的分类?
- GC什么时候开始?
JVM面试专题解析与拓展!
[外链图片转存中…(img-bF4cvKH5-1711894252790)]
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门即可获取!