Как отправить 1000 запросов XHTTP с максимальным количеством параллельных запросов - PullRequest
1 голос
/ 13 июля 2020

У меня есть приложение Angular, которое должно отправлять N запросов XHTTP, где 1 <= N <= 10000. </p>

Приложение должно обрабатывать его как можно быстрее, поэтому желательно, чтобы несколько активных запросов XHTTP одновременно, с помощью слайд-окна для нескольких запросов одновременно. Использование WebSocket или другого потокового решения невозможно из-за ограничений серверного API.

Моя первая идея заключалась в том, чтобы использовать что-то вроде Rx JS 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()

Есть идеи, как решить эту проблему? Rx JS похоже, что решение для этого уже написано.

1 Ответ

3 голосов
/ 13 июля 2020

Вы можете попробовать использовать операторы Rx JS bufferCount и concatMap вместе с forkJoin().

From bufferCount docs:

Собирать передаваемые значения до тех пор, пока не будет выполнено заданное число, передать как массив.

Таким образом, он собирает n количество уведомлений и отправляет его как массив. Затем мы могли бы передать массив через forkJoin() для n количества параллельных запросов.

Попробуйте следующее

Я предполагаю, что 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, либо сегментирование домена. И если ни то, ни другое невозможно, лучше буферизовать запросы на количество запросов меньше * максимально допустимого лимита.

* Очевидно, если вы уверены на 100% никакие другие запросы не будут отправляться к тому же домену во время процедуры буферизации, тогда вы можете буферизовать до макс. допустимый предел.

...