如何以最大并行请求数发送1000个XHTTP请求



我有一个Angular应用程序,它需要发送N个XHTTP请求,其中1<=N<=10000.

应用程序需要尽可能快地处理它,因此最好同时有多个活动的XHTTP请求,同时有一个多个请求的滑动窗口。由于服务器端API的限制,使用WebSocket或其他类似流的解决方案是不可能的。

我的第一个想法是使用RxJS forkJoin之类的东西,但我很难限制并发请求的数量。据我所知,API对最大请求数有限制,例如Chrome只允许8个同时请求。

我找到的大多数解决方案/教程要么a.(不限制并发连接的最大数量,要么b.(不动态更新(超时解决方案对此任务无效(。

例如:

const test = () =>
request(`https://swapi.co/api/people/1/`)
.pipe(
delay(1000),
switchMap(response => from(response.films)),
concatMap((url: string) => request(url).pipe(delay(1000))),
scan((acc, res) => [...acc, res.title], []),
tap(console.log)
)
.subscribe()

这对我来说并不好,因为限制是通过延迟实现的,但我想实现类似于基于线程的解决方案:最多有Y个并发连接,如果一个连接完成,则会立即启动新的请求。

const test = () =>
request(`https://swapi.co/api/people/1/`)
.pipe{
switchMap(response => from(response.films)),
specialOperatorIAmLookingFor((url: string) => request(url), 8),   // where '8' is the maximum number of paralell requests
scan((acc, res) => [...acc, res.title], []),
tap(console.log)
)
.subscribe()

有什么想法可以很好地解决这个问题吗?RxJS觉得应该有一个已经编写好的解决方案。

您可以尝试将RxJSbufferCountconcatMap运算符与forkJoin()一起使用。

来自bufferCount文档:

收集发射的值,直到满足提供的数字,发射为大堆

因此它收集n数量的通知并将其作为数组发送。然后,对于n数量的并行请求,我们可以通过forkJoin()传递数组。

尝试以下

我假设this.urls是类似于的HTTP请求的集合

urls = [
this.http.get('url1'),
this.http.get('url2'),
this.http.get('url3'),
...
];

然后请求触发代码看起来像

bufferedRequests() {
from(this.urls).pipe(
bufferCount(6),      // <-- adjust number of parallel requests here
concatMap(buffer => forkJoin(buffer))
).subscribe(
res => console.log(res),
err => console.log(err),
() => console.log('complete')
);
}

根据Chromium工程师的评论,最大连接到主机/域限制的实际解决方案是使用WebSockets或域碎片。但是,由于您提到这在您的环境中是不可能的,您可以使用缓冲请求解决方法。

然而,我不会试图缓冲到最大限度。如果你向同一个域发送的请求超过了允许的最大值,你可以看到,在上述请求完成之前,额外的请求实际上会滞后。因此,假设要缓冲到允许的最大限制,并且您的应用程序从应用程序工作流所依赖的其他地方向同一域发送额外请求,则整个应用程序可能会被节流。

因此,最好使用WebSockets或Domain sharding。如果两者都不可能,最好将请求缓冲到小于允许的最大限制*的请求数

*显然,如果您100%确定在缓冲过程中不会触发对同一域的其他请求,那么您可以缓冲到允许的最大限度

最新更新