Где используется Kafka: сценарии и установки

Содержание
Четыре установки
Сбор логов
Событийные микросервисы
Потоковая обработка
Многоконтейнерная установка в Docker Compose
Когда Kafka не нужна
Похожие статьи

Четыре установки

Одно и то же ядро Kafka — дописываемые топики, группы консюмеров, повторное чтение — обслуживает очень разные архитектуры. Ниже четыре установки в порядке роста сложности, каждая — минимальная рабочая конфигурация. Последняя — полный многоконтейнерный проект, который можно запустить.

Сбор логов

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

# каждый сервис дописывает в свой топик; ротацией занимается retention web-1 -> топик logs-web api-2 -> топик logs-api worker-3 -> топик logs-worker # консюмеры в своих группах — каждый видит все события: холодное хранилище <- все топики логов поисковый индекс <- все топики логов # пейджер: только severity >= error алерты <- топик logs-critical

Создать топик с недельным хранением для таких данных:

Создание топика

kafka-topics.sh --create --topic logs-web --bootstrap-server kafka:9092

Событийные микросервисы

Сервисы перестают вызывать друг друга и начинают объявлять факты. Сервис заказов дописывает order.placed в один топик и идёт дальше; резервирование склада, письма и аналитика читают этот топик каждый в своём темпе. Добавить четвёртую реакцию — скажем, антифрод — значит развернуть ещё одну группу консюмеров, причём вся история доступна для перечитывания с первого дня. Без изменений в сервисе заказов, без простоев.

Контракт, на котором всё держится, — схема событий: держите события маленькими, версионированными и обратно совместимыми, потому что старые события переживают любой деплой консюмеров.

Потоковая обработка в реальном времени

Когда вопрос — про сам поток: сколько оформлений в минуту, где группируются ошибки, — потоковый процессор читает топики и пишет производные топики обратно. Подсчёт слов поверх топика кликов — канонический пятиминутный пример; боевые задачи добавляют окна (агрегаты за минуту) и соединения с медленно меняющимися таблицами. Kafka Streams и ksqlDB закрывают этот паттерн без отдельного кластера обработки при умеренных нагрузках.

Многоконтейнерная установка в Docker Compose

Полная картина: три контейнера в одной Compose-сети — API магазина, принимающее HTTP-заказы, складской воркер и сама Kafka, причём каждое слово между сервисами идёт через топик. API никогда не вызывает воркер напрямую, а воркер никогда не опрашивает API.

Структура проекта

# shop/ — всё ниже лежит в одном каталоге compose.yaml producer/Dockerfile producer/requirements.txt producer/app.py consumer/Dockerfile consumer/requirements.txt consumer/worker.py

compose.yaml — один KRaft-брокер плюс два сервиса приложений

# compose.yaml — одиночный KRaft-брокер, ZooKeeper нигде нет services: kafka: image: apache/kafka:latest container_name: shop-kafka ports: - "9092:9092" environment: KAFKA_NODE_ID: 1 CLUSTER_ID: MkU3OEVBNTcwNTJENDM2Qk KAFKA_PROCESS_ROLES: broker,controller KAFKA_LISTENERS: PLAINTEXT://:9092,CONTROLLER://:9093 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092 KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka:9093 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true" # один брокер: факторы репликации — только 1, иначе создание топиков зависнет KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 producer: build: ./producer container_name: shop-producer ports: - "8000:8000" depends_on: - kafka consumer: build: ./consumer container_name: shop-consumer depends_on: - kafka

Строки про факторы репликации — те, что все забывают: значения по умолчанию рассчитаны на три брокера, а на одиночном создание топиков виснет навсегда. В advertised listeners — имя сервиса Compose kafka: именно по этому хосту должны стучаться оба Python-сервиса.

producer/Dockerfile и зависимости

# producer/Dockerfile (consumer/Dockerfile такой же, с worker.py) FROM python:3.12-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY app.py . CMD ["python", "app.py"] # requirements.txt — одна строка: kafka-python

producer/app.py — HTTP на входе, Kafka на выходе

import json import time from http.server import BaseHTTPRequestHandler, HTTPServer from kafka import KafkaProducer producer = KafkaProducer( bootstrap_servers="kafka:9092", value_serializer=lambda item: json.dumps(item).encode("utf-8"), ) class OrderHandler(BaseHTTPRequestHandler): def do_POST(self): length = int(self.headers.get("Content-Length", 0)) payload = self.rfile.read(length).decode("utf-8") producer.send("orders", {"raw": payload, "at": time.time()}) producer.flush() body = b"accepted" self.send_response(200) self.send_header("Content-Length", str(len(body))) self.end_headers() self.wfile.write(body) HTTPServer(("0.0.0.0", 8000), OrderHandler).serve_forever()

consumer/worker.py — Kafka на входе, резерв склада на выходе

import json from kafka import KafkaConsumer consumer = KafkaConsumer( "orders", bootstrap_servers="kafka:9092", group_id="stock-keepers", value_deserializer=lambda blob: json.loads(blob.decode("utf-8")), auto_offset_reset="earliest", ) for message in consumer: order = message.value print("reserve stock for", order, flush=True)

Group id — ручка масштабирования: запустите трёх воркеров через --scale consumer=3, и Kafka разложит партиции топика между ними. Упавший воркер после рестарта продолжит с зафиксированного офсета — ни один заказ не обработается дважды и ни один не потеряется.

Запуск: сначала брокер, потом приложения

docker compose up -d kafka

Дождитесь, пока docker compose logs kafka покажет стартовавший брокер, затем поднимайте приложения (в два шага, потому что depends_on упорядочивает старт, но не ждёт готовности, — консюмер, стартовавший при холодном брокере, упадёт вместо повторных попыток):

docker compose up -d --build

Отправить заказ, посмотреть на воркер

curl -X POST localhost:8000 -d "{"sku":"book","qty":2}"

docker compose logs -f consumer

Строка reserve stock for … в логе доказывает весь путь: HTTP → продюсер → топик orders → консюмер. Разобрать всё можно командой docker compose down; добавьте -v, чтобы удалить и данные брокера.

Когда Kafka не нужна

Три честных случая против. Первый — запрос/ответ: если вызывающий ждёт ответа, пара топиков всегда проиграет HTTP-вызову или RPC. Второй — крошечная нагрузка: несколько сообщений в минуту потянет лёгкая очередь (или таблица в базе) с куда меньшим хозяйством, чем даже один брокер. Третий — строгий глобальный порядок от многих писателей: Kafka упорядочивает только внутри партиции, так что проекты с единой мировой последовательностью будут бороться с инструментом, а не пользоваться им.

Article author: Arthur Isaev

Похожие статьи
Kafka

Search this site

Channel @aofeed Chat @aofeedchat

Contacts and cooperation:
I recommend our hosting beget.ru
Write to info@urn.su, info@aredel.com if you:
1. Want to write an article for our site or translate an article into your native language.
2. Want to place thematically relevant ads on the site.
3. Ads on my site pass maximum censorship. If you see an ad block unsuitable for school-age children, shocking or misleading - please contact us by e-mail
4. Found a mistake, inaccuracy, bug, etc. on the site. ... .......
5. Articles can be shared on social media by clicking a network icon: