Объяснение через QnA
Недавно в своей работе я столкнулся со сценарием, когда приложению нужно было потреблять сообщения из нескольких очередей. Мне было интересно, как Kafka удается надежно предоставлять такую возможность потребителям.
У меня было много вопросов, на которые мне нужно было получить ответы, прежде чем приступить к реализации такого дизайна, и я хотел понять, как работает Kafka в таком сценарии.
Давайте рассмотрим некоторые из этих вопросов и ответы, которые я нашел во время своих поисков.
Q1. Разрешено ли в Kafka одной группе потребителей одновременно использовать сообщения из нескольких тем?
А. Да, дизайн Kafka позволяет потребителям из одной потребительской группы получать сообщения из разных тем.
Протокол, лежащий в основе consumer.poll()
, позволяет отправлять запросы для нескольких разделов (в том числе по темам) в одном запросе.
Когда вызывается consumer.poll()
, FetchRequest
объекты отправляются брокерам, на которых размещаются лидеры разделов, и возвращаются все, т. е. max.poll.records
, поставленные в очередь сообщения.
consumer.poll()
возвращает карту тем с записями для подписанного списка тем и разделов.
Q2. Как подписаться на несколько тем?
A.
consumer.subscribe(Arrays.asList(topic1, topic2))
Да, это просто. Поняв, что потребительский API предоставляет эту возможность, я был уверен, что Kafka должен обрабатывать такой сценарий под капотом, но мне было любопытно узнать больше.
Q3. Как Kafka гарантирует, что темы не будут голодать?
А. Сообщения помещаются в очередь, начиная с первого раздела, если в текущем разделе больше нет сообщений, но есть еще байты для заполнения, сообщения из следующего раздела будут помещены в очередь до тех пор, пока не закончатся сообщения или буфер полный.
После того, как потребитель получит буфер, он разделит его на CompletedFetches
, где один CompletedFetch
содержит все сообщения одного раздела темы, CompletedFetches
ставятся в очередь.
Поставленные в очередь CompletedFetches
логически объединяются в одну большую очередь, и, поскольку запросы к каждому разделу отправляются параллельно, они могут смешиваться друг с другом.
consumer.poll()
будет считывать и удалять из очереди в most max.poll.records
из этой сглаженной большой очереди.
Последующие запросы на выборку исключают все разделы тем, которые уже находятся в сглаженной очереди.
Это означает, что у вас не будет зависающих сообщений, а потребление сообщений происходит в циклическом режиме, но у вас может быть большое количество сообщений из одной темы, прежде чем вы получите большое количество сообщений для следующей темы.
Q4. Как совершаются смещения?
A. Смещения, совершенные потребителями, хранятся в специальной теме Kafka под названием __consumer_offsets
, в которой сохраняются смещения для каждого раздела каждой темы.
Q5. Как обеспечить оптимальную пропускную способность?
A. Чтобы обеспечить оптимальное потребление сообщений из разных тем и избежать больших пакетов сообщений из одной темы за другой, вам может потребоваться обратить внимание на следующие свойства:
- Размер сообщения — размер сообщения, получаемого из темы.
fetch.min.bytes
— минимальное количество байтов, которое потребитель хочет получить от брокера.max.partition.fetch.bytes
— Максимальное количество байтов, которое будет использовано на один раздел.