循环请求报204问题分析
背景
商家自主添加配件需求(Freemarker+JQuery
前后端未分离项目)中,追加配件弹窗内批量复制粘贴配件会循环调用获取联想词接口,如果复制粘贴的配件名称很多(20+),只有一部分请求成功(状态码200)返回响应体,其他请求成功(状态码204)但没有返回响应体。
【循环请求报204问题分析】
问题分析
对比发布询价页、追加配件页发现这三个页面都有同样的问题,为什么循环并发调用接口会报204呢?跟运维、架构沟通后发现,这个问题的根源是网关层多了防爬、限流处理,因为当我们的系统被频繁的请求的时候,就有可能 将系统压垮,有了网关,那么就可以在网关系统做限流,因为所有的请求都需要先通过网关系统才能路由到微服务中。
文章图片
令牌桶算法
令牌桶算法是比较常见的限流算法之一,大概描述如下:
1)所有的请求在处理之前都需要拿到一个可用的令牌才会被处理;
2)根据限流大小,设置按照一定的速率往桶里添加令牌;
3)桶设置最大的放置令牌限制,当桶满时、新添加的令牌就被丢弃或者拒绝;
4)请求达到后首先要获取令牌桶中的令牌,拿着令牌才可以进行其他的业务逻辑,处理完业务逻辑之后,将令牌直接删除;
5)令牌桶有最低限额,当桶中的令牌达到最低限额的时候,请求处理完之后将不会删除令牌,以此保证足够的限流
如下图:
文章图片
在cass-webagent
网关项目中,限流配置如下:
icec:
limiter:
enabled: true
pathConfig:
burstCapacity: 10 #令牌桶的容量,同一个地址允许在一秒钟内完成的最大请求数
replenishRate: 5 #允许用户每秒处理多少个请求
routeConfig:
burstCapacity: 50 #令牌桶的容量,同一个服务允许在一秒钟内完成的最大请求数
replenishRate: 20 #允许用户每秒处理多少个请求
customConfigs: #自定义令牌桶的容量
- name: "path:/agentBuy/decodePartNo"
config.burstCapacity: 500
- name: "path:/agentBuy/getFastOEMore"
config.burstCapacity: 500
- name: "path:/maindata/llq/getDitchPriceSingle"
config.burstCapacity: 100
#- name: "route:web-market"
#config.burstCapacity: 51
当用户一秒内请求数量超过20个时,可能有一部分请求返回204(
no content
)文章图片
解决方案 1、前端控制每秒的请求并发数
比如,每个一个时间段发送一定量级的请求,利用一个伪死循环阻塞主线程
//第一种,使用while循环
function sleep(delay) {
var start = (new Date()).getTime();
while((new Date()).getTime() - start < delay) {
continue;
}
}//或者使用for循环
function sleep(delay) {
for(var t = Date.now();
Date.now() - t <= d;
);
}
2、在网关增加自定义某些接口路径允许用户每秒处理的请求量
3、将循环调用改成批量接口,这才是最彻底的解决方案
总结 本文仅仅是这类问题做一个分析记录,在开发中我们要避免这种循环调用接口的场景。
推荐阅读
- 参保人员因患病来不及到指定的医疗机构就医,能否报销医疗费用()
- 【1057快报】深入机关,走下田间,交通普法,共创文明
- 调取接口时报404错误(ID:16)
- 2019年第22周报
- https请求被提早撤回
- 遇到不正当请求怎么办
- whlie循环和for循环的应用
- 东望志愿者的精神
- 能力和自信的良性循环
- 接口|axios接口报错-参数类型错误解决