Kafka и картошка

Так уж получилось что как держатель профессии системного анализа я не раз в ходе занятий со студентами, собеседований, и ассесментов сталкивался с проблемой непонимания базовых принципов и ценностей работы сервисов очередей. Люди не понимают ни как оно работает ни для чего нужно. И раз уже до ИТ мне посчастливилось почти 10 лет отслужить в армии то пример, который очень зашел даже далеким от ИТ людям, со временем родился сам собой.

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

1d9292e357df7bb0a8b41f200a84fc93.png

Этап 1. Разделение зон ответственности сервисов

На первом этап мы выделяем по одному солдату на два участка работы: первый будет приносить картошку из погреба, а второй — чистить то, что принес первый и сбрасывать в кастрюлю для варки. Запускаем процесс, смотрим что получилось:

929b3e84be846eb6f361b45ee476bf75.png

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

Этап 2. Масштабирование

Видя проблему первое, что приходи в голову неопытным командирам — «Надо накинуть еще людей» (горизонтальное масштабирование) и возможно — как то оптимизировать чистильщика чтобы работал побыстрее — «Накинуть люлей чистильщику, выдать ему наконец острый нож» (вертикальное масштабирование).

Делаем это упражнение и узким местом становится носильщик. Пытаемся таким же образом оптимизировать носильщика и накинуть ресов уже ему, но так как вся картошка разная и все люди работают в разном темпе — сбалансировать работу не получается. Кто то все равно простаивает.

ea4f67e5fe75a593fe05941aa0c43f9b.png

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

Этап 3. Сервис очередей

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

bcbc493df3088bcb4c191143201d0d0e.png

Как вы уже наверное поняли, роль сервиса очередей у нас тут играет тот самый таз. Сообщения в очереди — картошка. Носильщики начинают называться умным словом »продюсер», а чистильщики — »консьюмер».

Теперь поговорим айтишным языком как же можно еще оптимизировать процесс, чтобы он шел быстрее:

  • Увеличиваем размер сообщения: носильщики начинают носить картошку из погреба не по одной, а сразу ведрами. Это называется умным словом «массив».

  • Выдаем чистильщику электрический станок для чистки, в который он может загрузить сразу все ведро или даже три. Это уже «Batch processing».

Этап 4. Анализ рисков

Что же может пойти не так:

  • Мы с вами в армии. Если солдаты оставили картошку в тазу и ушли спать, то утром они найдут пустой таз, из которого всю картошку украли. Это называется »Retention time». В реальной жизни он используется для того, чтобы таз не переполнялся, так как обработанные сообщения из Kafka никуда не деваются, просто условно помечаются как обработанные. Это позволяет, например, при необходимости обработать сообщение еще раз после ошибки.

  • Таз могут опрокинуть. Для этого картошка делится не несколько тазов. Это называется »партиции». Если один таз опрокинут — работа не встанет пока будут собирать картошку из него обратно.

  • Таз может опустеть. Количество картошки в тазу называется »Consumer lag». И если он слишком сильно растет — таз может либо начать переполняться и терять сообщения (картошка посыпалась на пол, по умному — Retention bytes). Надо за этим следить и заранее масштабировать чистильщиков или освобождать носильщиков.

Этап 5. Какие есть возможности?

Какой-нибудь умный командир может потребовать доставать из таза картошку, например, по цвету.

  • Надо помнить, что сервис очередей это не база данных, и все что там лежит — достается так, как отдает очередь

  • Если очень хочется — можно настроить партиционирование по разным тазам в зависимости от цвета картошки

  • Можно сделать так, чтобы из разных тазов‑партиций картошку чистили разные группы людей. Это называется »Консьюмер‑группа». Например, если синяя картошка идет на жарку, а белая на варку — разные консьюмер группы могут по разному обрабатывать сообщения.

© Habrahabr.ru