Как лучше организовать очередь сообщений для их разбора по графику?

По REST API приходят 10-50 тыс. запросов в минуту.
Обрабатывать нужно не все, а только ~2% ( так как большинство запросов это дубли )
Real-time не нужен, достаточно раз в минуту их обрабатывать.

Подскажите как лучше это организовать ?
Использовать какой-то готовый инструмент для построения очереди ?
Или просто как-то складывать в файл (на чём такое лучше писать - nodejs, python, go ?), и потом этот файл разбирать по крону ?

Дополнительно:

Обрабатывать нужно все запросы на уровне своего REST API, но на сколько я понял, то ты пытаешься топорным методом решить проблему с большим кол-вом лишних запросов к бэку, если ты например пользуешься nginx то там даже для каждого location - можно настроить лимиты запросов, период между запросами, и т.д ( гугл в помощь ) и если чувак нарушил твои лимиты - просто блочишь все запросы с его ip или проксируешь все дальнейшие его запросы на какой-нибудь чужой api)

Или просто как-то складывать в файл

- а чё не в карман ?)

  • Обрабатывать нужно не все, а только ~2% ( так как большинство запросов это дубли )

    что так? На каком уровне дубли? Всё тело сообщения или какая-то её часть?

  • Клиент использует CRM систему, и там видимо это не баг а фича - дёргать api при каждом изменении сущности. Подписаться, только на нужные события нельзя. Поправить её не представляется возможным, т.к. это большое saas решение.

    Тело сообщения - это данные в json, данные совпадают не полностью, т.к. в них есть временные метки

  • для их разбора по графику

    Почему по графику? А просто по мере поступления разве нельзя?

  • Иерокопус Таманский,
    чтобы накопить дубли, чтобы их отбросить и обработать только не задублированные.
    важно обработать последний запрос, т.е. последний дубль не пропустить, остальные можно проигнорировать.
  • Можно ведь не рисковать, а обработать первое сообщение, а остальные отбросить.
  • И как знать какое сообщение является последним?
  • Иерокопус Таманский,
    никак. копим очередь, отбрасываем все дубли обрабатываем последнее в этой очереди (может оно и будет последним, а может совсем последнее будет в следующей очереди)
  • Обрабатывать нужно не все, а только ~2% ( так как большинство запросов это дубли )

    Может лучше с дублями разобраться? Рейт-лимиты какиенибудь ввести или группировать их?

    Клиент использует CRM систему, и там видимо это не баг а фича - дёргать api при каждом изменении сущности.

    В таком сценарии я бы взял кафку и просто по очереди все события обрабатывал. Лишние легко можно будет откинуть.

  • Ответы:

    Выглядит как попытка сделать костыль, не в ту сторону смотрите

    • Клиент использует такую CRM систему, и там видимо это не баг а фича - дёргать api при каждом изменении сущности. Подписаться, только на нужные события нельзя.
      Поправить её не представляется возможным, т.к. это большое saas решение.

    Я-бы разобрался с дублями. Если есть система которая продуцирует их - то наверное можно
    как-то решить этот вопрос на уровне источника. Это performance issue который нужно обусждать.

    Можно строить всякие архитектуры на базе очередей или идемпотентных баз но при этом главная
    причина (сетевой траф) будет непофикшена а по сути спрятана под ковер.

    • Клиент использует CRM систему, и там видимо это не баг, а фича - дёргать webhook при каждом изменении сущности. Подписаться, только на нужные события нельзя.
      Поправить её не представляется возможным, т.к. это большое saas решение.
    • gitPush, а какие там запросы? GET? POST?
    • POST, данные приходят в json, немного отличается каждый запрос ( как минимум временной меткой )
    • gitPush, можно взять все оставшиеся поля и сделать из них хеш и сохранить в какую-то табличку. Если хеш уже был - значит такой документ уже обрабатывался.

      Логика на вид простая. И очередь не нужна.

    Вроде как, такое кол-во запросов вполне по силам современным реактивным серверам. Для тех кто знает Java, пара полезных лекций по реактивщине: раз, два. К сожалению, не нашёл видео с замерами производительности.
    Вопрос можно ли обрабатывать запросы по мере их поступления это не вопрос производительности web-сервера, это вопрос как долго ты будет готовить данные для ответа. Если там нет долгих вычислений или запросов к другим сервисам - обрабатывай в реальном времени.
    Если есть - используй очередь. Какую именно - вопрос о количестве данных. Если одновременно обрабатываемые данные не помещаются в память - используй Kafka, Rabbit и т.п. Если помещаются - организуй FIFO буфер в памяти, коллекция Queue есть во всех нормальных языках (ну, или её можно сделать на основе связного списка).
    Присоединюсь к предыдущим ораторам: надо разбираться с дублями. Ты говоришь что для снижения нагрузки можно отвечать не на все запросы, а только на последний в серии. А как определить что только что прилетевший запрос - последний?
    На чём писать - на том что знаешь. А если не получится - искать программиста на Java 🙂

    Раз в минуту: cron
    Очереди: AWS SQS, RabbitMQ, Apache Kafka
    Лучше писать на том, что вы знаете и в чём разбираетесь. Хоть pascal.

    • AWS SQS, RabbitMQ, Apache Kafka - любой подойдёт для данной задачи ?
      на чём лучше = на чём возможно такое реализовать ?
      например понятно, что php такую нагрузку не выдержит. pascal тоже плохой пример - там плохо с многопоточностью)
    • gitPush, а почему пхп не выдержит то?
    • gitPush, Любой подойдёт. PHP выдержит, как и pascal. Вопрос в том, как вы будете их использовать и как масштабироваться.
    • Дмитрий, на сервере установлена связка php-fpm+nginx
      то есть при каждом запросе, будет запускаться свой экземпляр php, пару сотен таких одновременно и сервер ляжет.
    • gitPush, ну вопрос как быстро отработает ваш скрипт. собственно класть в очередь вы через что будете? тем же php. просто обработка будет происходит в воркере.

      сделайте php <?php echo 'Hello world'; ?> и он у вас и 100 тысяч запросов в минуту примет

    • Дмитрий,
      > ну вопрос как быстро отработает ваш скрипт.
      быстро, там практически и будет <?php echo 'Hello world'; ?>
      но как я понимаю, тут проблема в накладных расходах на поднятие самого экземлемера php
      100 тысяч запросов в минуту - это одновременно ~1,6к экземпляров php
    • gitPush, ну во-первых он не будет поднимать особенно если включите static. и он будет их держать поднятыми. во вторых в php-fpm один рабочий процесс может принимать несколько запросов.
    • gitPush, экземпляр php-интерпретатора на каждый запрос только в php-cgi, для php-fpm и всяких mod_php один процесс будет обрабатывать много запросов (как настроишь столько и будет, главное чтобы памяти хватило).

    Можно писать в тот же redis, для данных с одинаковым хэшем дублирования не будет. Ну и есть очереди на основе redis разные, зависит от вашего языка.
    А так, соглашусь с предыдущим оратором - надо бы разобраться с дублированием, откуда его столько...

     

    Для решения данной проблемы вы можете воспользоваться услугами фрилансеров. Мы выполним необходимую работу быстро и качественно.

     

      • Как лучше организовать очередь сообщений для их разбора по графику?Есть ответ
      • 07.04.2024
      Ответить

      Для организации очереди сообщений для их разбора по графику вам может пригодиться структура данных, такая как очередь (queue). Очередь - это структура данных, в которой элементы добавляются в конец и удаляются из начала.

      Для создания очереди сообщений вы можете использовать язык программирования PHP. Вот пример кода, который поможет вам организовать очередь сообщений:

      class MessageQueue {
          private $queue = [];
      
          public function push($message) {
              array_push($this->queue, $message);
          }
      
          public function pop() {
              return array_shift($this->queue);
          }
      
          public function isEmpty() {
              return empty($this->queue);
          }
      }
      
      // Пример использования
      $messageQueue = new MessageQueue();
      $messageQueue->push("Сообщение 1");
      $messageQueue->push("Сообщение 2");
      
      while (!$messageQueue->isEmpty()) {
          $message = $messageQueue->pop();
          echo $message . "

    Оставить комментарий