高可用之接口限流
限流方案
- 请求存消息队列,实例根据自己处理能力,拉取消息消费
- 线程池控制,排满线程池队就直接失败
- 请求拦截器,维护一个信号量控制同时并发处理数,超出排队值(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