高可用之接口限流
限流方案
- 请求存消息队列,实例根据自己处理能力,拉取消息消费
- 线程池控制,排满线程池队就直接失败
- 请求拦截器,维护一个信号量控制同时并发处理数,超出排队值(require排队)就返回429状态码
信号量方案
Spring管理唯一bean,内含唯一的限流拦截器。以下是关键变量
Semaphore current_model_semaphore 所有请求都共用一个信号量;
int semaphoreSize 信号量有多少permits
int semaphoreMaxQueueSize 设定多少请求可以排队,超了就抛异常了
List
ConcurrentMap<String, AtomicInteger> concurrents 接口对应有多少个当前处理数
Boolean returnTooManyRequestError 是否启用429返回
处理逻辑
- 判断当前请求的url是否匹配apiFilterList其中一个,不匹配返回filter chain后续处理
- 如果未启动429返回,则阻塞地获取信号量。获取成功则继续处理,超时会触发 InterruptedException ,捕捉后抛业务异常
- 如果请求头没有标识本次请求为最后一次重试,调用tryAcquire()获取信号量的permits,如果没有现成可用的permits,立即返回,接着就返回429状态码,结束请求
- 如果已达最大重试次数,那么本次请求应该更加“倔强”地等。如果排队获取信号量的线程还没达到设定的最长semaphoreMaxQueueSize,那么就acquire等待。如果队伍已满,只能放弃等待直接返回429.
- 所有acquire()后,在finally块做信号量的release()
graph TB
1{判断当前请求的url是否匹配apiFilterList其中一个}
2[拦截器返回交给filter chian后续处理]
3{是否启用429返回}
4{acquire阻塞地获取信号量}
5[捕获InterruptedException后抛业务异常]
6[正常走业务逻辑]
7{是否达到最大重试次数}
8{tryAcquire有无现成的permits}
9[快速失败返回429]
10{是否达到最大排队长度}
1--无需限流-->2
1--需要限流-->3
3--未启用429-->4
4--超时-->5
4--成功获取-->6
3--启用429-->7
7--否-->8
8--无-->9
8--有-->6
7--是-->10
10--是-->9
10--否-->4