Много маленьких очередей в Кафке - как сохранить балансировку нагрузки при горизонтальном масштабировании? - PullRequest
1 голос
/ 13 мая 2019

Я строю систему распространения сообщений с использованием Kafka. Он будет обрабатывать десятки тысяч событий в секунду (все имеют одинаковую структуру) и будет иметь тысячи возможных получателей. Сообщения будут поступать в систему, помещаться в очередь в Кафке, а затем отправляться получателю. Требования:

  • Порядок сообщений для конкретного получателя должен быть сохранен, потеря сообщений не допускается.
  • Скорость, с которой приходят сообщения для каждого получателя, и скорость, с которой каждый получатель обрабатывает сообщения, могут сильно отличаться, и получатели могут иметь длительные простои (например, неделю), поэтому каждому получателю нужна своя очередь для прохождения (или остановки) на своем собственный курс.
  • Остановленный получатель не должен влиять на поток сообщений для других получателей, а также не должен снижать пропускную способность.
  • Новые получатели могут быть добавлены в любое время во время выполнения, и система должна начать отправлять сообщения новому получателю в течение разумного времени (но не обязательно сразу).
  • Приложение, которое принимает и обрабатывает сообщения от Kafka и отправляет их различным получателям, должно иметь возможность масштабирования до нескольких узлов. Каждый экземпляр должен обрабатывать часть работы, независимо от того, разделен ли он на мощность обработки сообщений, количество получателей или каким-либо другим образом, он не должен быть идеально сбалансированным, но он должен быть в целом масштабируемым во время выполнения без простоев и восстанавливаться. из-за сбоев узла.

Будучи новичком в Кафке, я не уверен, как его смоделировать. Сначала я думал о теме на получателя , с одним разделом на тему. Я знаю, что Kafka 2.0 может поддерживать неограниченное количество тем, так что это не проблема.

  • Вы можете использовать шаблоны для подписки на несколько тем, которые будут автоматически обновляться периодически. Таким образом, любой новый получатель (имеющий собственную тему) автоматически начнет потребление узла.
  • Но тогда какой механизм разделил бы темы между узлами приложения? Порядок обработки должен быть сохранен, поэтому каждая тема должна обрабатываться только одним узлом.
  • Когда появляется узел приложения, как он узнает, какие темы он должен использовать? Когда узел выходит из строя, как его темы будут распространяться на другие узлы?

Это звучит как механизм групп потребителей. Поэтому я искал один раздел на получателя . В Kafka каждый раздел - это его собственная очередь, которая может развиваться в своем собственном темпе, и разделы раздаются и распределяются между потребителями в группе потребителей автоматически, именно то, что мне нужно! Но проблема с разделами заключается в том, что они предназначены как механизм распределения нагрузки для одного потока данных, поэтому у них есть несколько ограничений.

  • Разделы не являются полностью динамическими. Наличие раздела для каждого получателя будет означать добавление раздела каждый раз, когда в систему добавляется новый получатель. Это может привести к перебалансированию и, по-видимому, неправильно сочетать функциональные и нефункциональные проблемы, связывая бизнес-объект с конфигурацией инфраструктуры.
  • Разделы нумеруются, так как я могу сопоставить имя получателя (строку) с номером раздела последовательно 1 к 1? Я думаю, что я мог бы использовать генератор последовательности для нумерации моих получателей, но это похоже на взлом на вершине неправильного решения. Если мне когда-нибудь понадобится удалить получателя, это оставит дыру в нумерации. Я не хочу, чтобы более одного получателя были сопоставлены одному и тому же разделу, потому что остановка одного получателя повлияет на остальных.
  • Должен ли я предварительно распределить разделы, чтобы предотвратить изменение баланса? Если у меня 5000 получателей, и ожидается, что их число будет расти, я должен определить 20 000 разделов, и только 75% из них останутся неиспользованными на тот момент? Это предотвратит изменение баланса при каждом добавлении получателя, но выглядит как хак.

Как мне использовать Kafka для решения этой проблемы с очередями?Или, может быть, Кафка не подходит для работы?

1 Ответ

1 голос
/ 16 июня 2019

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

Я бы порекомендовал изучить Рабочий процесс Cadence для реализации вашего приложения.

Предложения Cadenceмножество других преимуществ по сравнению с использованием очередей для обработки задач.

  • Динамически создаваемые очереди задач.Количество очередей не ограничено.
  • Построены экспоненциальные повторы с неограниченным интервалом истечения
  • Обработка ошибок.Например, он позволяет выполнить задачу, которая уведомляет другую службу, если оба обновления не могут быть выполнены успешно в течение заданного интервала.
  • Поддержка длительных пульсирующих операций
  • Возможность реализации зависимостей сложных задач.Например, для реализации цепочки вызовов или логики компенсации в случае неисправимых сбоев ( SAGA )
  • Обеспечивает полную видимость текущего состояния обновления.Например, при использовании очередей все, что вы знаете, если в очереди есть несколько сообщений, и вам нужна дополнительная БД для отслеживания общего прогресса.С Cadence каждое событие записывается.
  • Возможность отмены обновления в полете.

См. презентацию , которая охватывает модель программирования Cadence.

...