Messaging & Queues

NATS

NATS — лёгкая шина обмена сообщениями на Go: адресация по subject, микросекундные задержки, а надёжное хранение добавляет встроенный JetStream.

Что такое NATS

NATS — лёгкая система обмена сообщениями: один бинарник на Go без внешних зависимостей, адресация по subject и микросекундные задержки. Open-source, проект CNCF. В базовом режиме (core NATS) это чистый pub/sub без хранения — доставили подписчикам и забыли; надёжная доставка, хранение и повтор истории добавляются встроенным слоем JetStream.

Главная идея — простота эксплуатации. Сервер весит порядка десятка мегабайт, стартует мгновенно, настраивается одним конфигом. Там, где Kafka требует кластера, JVM и постоянного внимания, NATS часто живёт обычным контейнером рядом с сервисами. Это не «Kafka для бедных», а другой компромисс: минимум веса и задержки в обмен на минимум встроенной обвязки.

Subject: адресация вместо очередей

Сообщение публикуется в subject — строку из слов через точку:

orders.eu.created
orders.us.created
telemetry.sensor42.temp

Подписчик указывает шаблон:

Шаблон Что поймает
orders.eu.created Точное совпадение
orders.*.created * — ровно одно слово: EU и US, но не orders.eu.v2.created
orders.> > — хвост любой длины: все события заказов

Никаких заранее созданных очередей и exchange объявлять не нужно: subject существует сам по себе, подписка на любой шаблон работает сразу. Это заметно упрощает жизнь по сравнению с RabbitMQ, где маршрут надо описать заранее.

Три модели обмена

  • Pub/sub — все подписчики subject получают копию сообщения.
  • Queue group — подписчики с одинаковым именем группы делят нагрузку: сообщение достаётся ровно одному. Так делают пул воркеров и балансировку без отдельного load balancer.
  • Request/reply — встроен в протокол: клиент публикует запрос с временным reply-subject и получает ответ. Выходит RPC поверх шины, который сам балансируется между отвечающими и не требует знать их адреса.
nats sub 'orders.>'                    # подписка с wildcard
nats sub --queue=workers 'jobs.new'    # воркер в queue group
nats req 'service.time' ''             # request/reply

Именно request/reply чаще всего и приводит команды в NATS: он заменяет паутину прямых HTTP-вызовов между сервисами, снимая вопрос service discovery — адресом становится subject.

Core NATS vs JetStream

Core NATS JetStream
Хранение Нет Да: память или диск
Гарантия at-most-once at-least-once, exactly-once по message ID
Консьюмер был офлайн Пропустил всё Дочитает после возвращения
Перечитать историю Нет Да
Задержка Микросекунды Выше: запись и репликация

Core NATS ничего не хранит: нет подписчика в момент публикации — сообщение исчезло. Это не недостаток, а осознанный дизайн, за счёт которого достигается скорость. Нужна надёжность — включают JetStream:

nats stream add ORDERS --subjects='orders.>' --storage=file \
  --replicas=3 --retention=limits --max-age=168h

Stream забирает сообщения из subject и хранит их заданный срок; консьюмеры читают из stream и подтверждают обработку. Реплики синхронизируются по Raft, так что --replicas=3 переживает потерю узла. Поверх JetStream работают ещё KV-хранилище и object store — часто этого хватает вместо отдельного Redis.

Топология: cluster, leaf node, supercluster

  • Cluster — узлы в full mesh, клиент подключается к любому. Порты: 4222 для клиентов, 6222 между узлами, 8222 — HTTP-мониторинг.
  • Leaf node — лёгкий узел на краю сети (площадка, филиал, устройство), который прозрачно прокидывает subjects в основной кластер и продолжает работать при обрыве связи.
  • Supercluster — соединение кластеров из разных регионов через gateways, без дублирования трафика между ними.

Эта топология — то, где NATS выигрывает у остальных: сотни точек на краю сети и единая адресация между ними. Сервер умеет говорить и по MQTT, так что устройства подключаются напрямую, без отдельного IoT-брокера.

Где NATS уместен, а где нет

  • Да: внутренняя шина между микросервисами в Kubernetes; request/reply вместо прямых вызовов; телеметрия и edge; события, где важна задержка, а потеря отдельного сообщения не критична.
  • Нет: терабайты истории и аналитика на потоке — JetStream умеет retention, но экосистема Kafka (Connect, Streams, готовые интеграции с DWH) сюда не переносится. Не заменяет он и RabbitMQ там, где нужны приоритеты сообщений и сложная маршрутизация на стороне брокера.

Отдельный практический плюс — цена входа. NATS спокойно живёт на скромном VPS или в sidecar-контейнере, тогда как Kafka требует трёх брокеров с NVMe ещё до первого сообщения.

Связанные термины

  • Брокеры сообщений — общий класс систем и терминология
  • Apache Kafka — тяжёлая альтернатива с богатой экосистемой
  • RabbitMQ — брокер с маршрутизацией на стороне сервера
  • MQTT — протокол для устройств, который NATS поддерживает нативно
  • Kubernetes — типичная среда, где NATS работает шиной
  • Микросервисы и монолит — задача, ради которой его ставят

Готовы запустить GPU-задачу?

Запустить GPU-сервер