Редуктор / агрегатор сообщений на основе превышения времени ожидания или количества

1

Я работаю над системой java SE (+netty), которая получает от клиентов сообщения разных типов, объединяет их и подталкивает агрегированные результаты в хранилище.

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

Задача кажется легкой, но я застрял в реализации. Очевидно, мне нужно собирать сообщения в некоторой структуре данных и проверять правила тайм-аута и количества для каждого элемента. Я думал о DelayedQueue<Delayed<List<MyMessages>>> (List<MyMessages> - это List<MyMessages> список сообщений).

DelayedQueue использует таймауты. Но неясно, как проверять максимальные количества и добавлять новые сообщения в списки эффективно. Я не хочу проверять все списки на каждое новое сообщение, ища правильный. И выглядит небезопасно для добавления данных в элементы Delayed<List>.

Какие структуры данных/архитектура подходят для системы, которую я пытаюсь создать? Думаю, такая проблема имеет правильное академическое имя и решение, что я должен делать Google?

Теги:
aggregate

1 ответ

0
Лучший ответ

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

Я бы предложил объединить оба: Получение потоков отслеживает, сколько элементов было накоплено, и уведомляет об агрегирующем потоке, если порог достигнут, а агрегатный поток отслеживает время.

Вы можете сделать это, упрощенно, примерно так:

final long maxWait = 1000;
final int maxMessages = 10;
final ArrayBlockingQueue<Message> queue;

final Thread aggregator = new Thread()
{
  @Override
  public void run() {
    try {
      ArrayList<Message> messages = new ArrayList<>();
      while ( true ) {
        messages.clear();
        queue.drainTo( messages );

        // Store messages

        this.wait( maxWait );
      }
    }
    catch ( InterruptedException e ) {
      // Handle this..
    }
  }
};

final Thread reciever = new Thread()
{
  @Override
  public void run() {
    Message message; // Get this from network
    queue.put( message );
    if(queue.size() > maxMessages) {
      aggregator.notify();
    }
  }
}

Это не обрабатывает вашу группу сообщений, но я уверен, что вы можете увидеть, как это можно экстраполировать для обработки нескольких очередей разных типов сообщений. Чтобы агрегатор учитывал только определенный тип сообщения, когда он уведомлялся, вы могли бы использовать более сложный механизм обмена сообщениями, а не ждать/уведомлять, например, ожидают ли очереди в очереди, где получение потоков в свою очередь может помещать очереди как "сообщения" "о очередях, которые необходимо объединить и сохранить.

  • 0
    Основная проблема такого агрегатора заключается в том, что он обрабатывает сообщения синхронно, одно за другим. Итак, если я получу сообщение типа с огромным временем ожидания - все остальные сообщения будут ждать. Вот почему я начал использовать DelayedQueue.
  • 0
    Можете ли вы объяснить, что вы имеете в виду, «обрабатывая это один за другим»? ArrayBlockingQueue может обрабатывать массовые операции, см. Выше использование dumpTo, которое берет все элементы, находящиеся в данный момент в очереди, и помещает их в этот ArrayList для агрегирования. Или вы имеете в виду, что он обрабатывает каждый тип сообщения синхронно в том смысле, что он будет ожидать синхронно в каждой очереди? Это правда. Вы можете обойти это, имея Timer или ScheduledExecutor, где вы можете настроить задания для запуска в будущем или отменить их на досуге.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню