若页面一次性接口请求上百个,阁下又当如何应对?

前言

问:假如页面一次性请求有上百个,你应该如何处理这种请求并发?

答:so easy!循环请求?肯定是不对的,否则一次性并发上百次请求,差点的服务器得崩溃了,我甚至一度以为你是在搞Dos攻击。我们可以通过任务队列的缓存来合理控制并发数据。

我们知道浏览器发起的请求最大并发数量一般都是 6~8 个,这是因为浏览器会限制同一域名下的并发请求数量,以避免对服务器造成过大的压力。本文思路的核心就是保持浏览器的最大并发请求,多出的请求数加入队列缓存。

1. 实现并发请求场景

我们现实一下简单的100次直接并发请求的场景,本地实现一个简单的前端页面和express后台服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
html复制代码<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./axios.min.js"></script>
</head>
<body>
</body>

<script>
// 请求模拟
const requestFn = () => {
return axios.get("http://127.0.0.1:8000/msg", {})
}
// 模拟直接并发100次请求
for (let i = 0; i < 100; i++) {
requestFn();
}
</script>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
js复制代码const express = require('express');
const app = express();

app.all('*', (req,res,next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Credentials", true);
next();
})

app.get("/msg", (req, res) => {
let count = 0;
for (let i = 0; i < 10000000; i++) {
count++
}
res.json({code :0, msg: `请求结果${count}`});
})

app.listen('8000',() => {
console.log('请求成功')
})

一次性并发上百个请求,要是配置低一点,又或者带宽不够的服务器,直接宕机都有可能,所以我们前端这边是需要控制的并发数量去为服务器排忧解难。

2. 优化并发请求场景

如下所示,定义一个 queue 用来缓存请求队列,定义一个参数 current 记录当前正常并发执行的接口请求数量。每一次循环请求时都会先将请求接口缓存在队列queue中,当前的并发的请求数量 current 小于默认最大的请求限制数量 limitCount时候,从队列头部中选择一个请求并开始执行,并且 current 数量+1,执行完成后current 数量-1,并且继续递归执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
html复制代码<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./axios.min.js"></script>
</head>
<body>
</body>

<script>
// 请求模拟
const requestFn = () => {
return axios.get("http://127.0.0.1:8000/msg", {})
}
// 实现一个并发控制的函数
const queue = [] // 请求池队列,用来缓存接口请求
let current = 0
const requestQueue = (limitCount = 6, callbackFn) => {
queue.push(callbackFn); // 入队列
const dequeue = () => {
while (current < limitCount && queue.length) {
current++;
const requestPromiseFactory = queue.shift() // 出列
requestPromiseFactory()
.then((res) => {
console.log('res =====>', res)
})
.catch(error => { // 失败
console.log(error)
})
.finally(() => {
current--
dequeue()
});
}
}
// 执行
dequeue()
}

for (let i = 0; i < 100; i++) {
requestQueue(6, requestFn)
}
</script>
</html>

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%