Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
NATS: система обмена сообщениями
NATS (Neural Autonomous Transport System) — это лёгкая, высокопроизводительная система обмена сообщениями между приложениями. Это open-source брокер для публикации-подписки (pub/sub) и запрос-ответ (request/reply) архитектур.
Аналогия для понимания
Представьте почтовый сервис:
- RabbitMQ — официальная почта с гарантией доставки, ненадёжная, требует подтверждения
- Kafka — оптовая почта, хранит всё, очень надёжная, но сложная
- NATS — курьерская доставка, быстро, просто, потеряет письмо, если никто не слушал
NATS фокусируется на скорости и простоте, пожертвовав гарантией доставки.
Основные концепции
1. Pub/Sub (Publish-Subscribe)
const { connect } = require('nats');
const nc = await connect({ servers: 'localhost:4222' });
// Подписчик
const subscription = nc.subscribe('orders.created', {
callback: (err, msg) => {
if (err) console.error(err);
else console.log('New order:', msg.data.toString());
}
});
// Издатель
const encoder = new TextEncoder();
nc.publish('orders.created', encoder.encode(JSON.stringify({
id: 123,
user: 'Ivan',
amount: 500
})));
2. Request-Reply (синхронные запросы)
// Responder (слушатель, который отвечает)
nc.subscribe('user.lookup', {
callback: (err, msg) => {
const userId = JSON.parse(msg.data.toString());
const user = { id: userId, name: 'Ivan' }; // Поиск в БД
msg.respond(encoder.encode(JSON.stringify(user)));
}
});
// Requester (клиент, который просит)
const reply = await nc.request(
'user.lookup',
encoder.encode('123'),
{ timeout: 5000 }
);
const user = JSON.parse(reply.data.toString());
console.log(user);
3. JetStream (очереди сообщений с гарантией)
const js = nc.jetstream();
// Создать stream
await js.addStream({
name: 'orders',
subjects: ['orders.>'],
storage: StorageType.File
});
// Опубликовать в stream
await js.publish('orders.created', encoder.encode(JSON.stringify(order)));
// Подписаться с гарантией доставки
const psub = await js.subscribe('orders.created', {
durable: 'order_processor', // Сохранит состояние
callback: (err, msg) => {
if (!err) {
processOrder(msg);
msg.ack(); // Подтверждение доставки
}
}
});
NATS vs другие системы
| Параметр | NATS | RabbitMQ | Kafka |
|---|---|---|---|
| Скорость | Очень быстро (1M msg/s) | Медленнее (50K msg/s) | Быстро (100K msg/s) |
| Простота | Очень простой | Средняя сложность | Сложный |
| Гарантия доставки | Только с JetStream | Встроенная | Встроенная |
| Памяти | Минимум | Среднее | Много |
| Масштабируемость | Хорошо | Хорошо | Отлично |
| Кластеризация | Встроена | Встроена | Встроена |
| Persistance | JetStream опционально | По умолчанию | По умолчанию |
Архитектура NATS
Producer1 --->
NATS Server
Producer2 ---> (вся обработка --> Consumer1
в памяти, очень) --> Consumer2
Producer3 ---> быстро --> Consumer3
Нет на диске, всё в памяти, поэтому ОЧЕНЬ быстро!
Примеры использования в backend
1. Микросервисная архитектура
// user-service
nc.subscribe('user.create', async (err, msg) => {
const user = JSON.parse(msg.data.toString());
await saveUser(user);
nc.publish('user.created', encoder.encode(JSON.stringify(user)));
});
// order-service
nc.subscribe('user.created', (err, msg) => {
const user = JSON.parse(msg.data.toString());
console.log('New user, send welcome email:', user.email);
});
2. Асинхронная обработка
// API endpoint
router.post('/orders', async (req, res) => {
const order = req.body;
// Быстро опубликовать, не ждать обработки
nc.publish('orders.new', encoder.encode(JSON.stringify(order)));
res.json({ id: order.id, status: 'created' });
});
// Background worker
nc.subscribe('orders.new', async (err, msg) => {
const order = JSON.parse(msg.data.toString());
// Долгая обработка: проверка платежа, отправка email
await processPayment(order);
await sendConfirmationEmail(order);
});
3. RPC (Remote Procedure Call)
// Service A
app.post('/user/:id', async (req, res) => {
const reply = await nc.request(
`auth.validate_token`,
encoder.encode(req.headers.authorization),
{ timeout: 2000 }
);
const isValid = JSON.parse(reply.data.toString());
// ...
});
// Service B (auth-service)
nc.subscribe('auth.validate_token', async (err, msg) => {
const token = msg.data.toString();
const isValid = validateToken(token);
msg.respond(encoder.encode(JSON.stringify(isValid)));
});
Когда использовать NATS
✓ Простые, высокопроизводительные pub/sub системы ✓ Микросервисы с низкой задержкой ✓ Real-time приложения (чаты, уведомления) ✓ Event streaming без гарантий доставки ✓ Request-reply паттерны (RPC) ✓ Когда простота и скорость важнее надёжности ✓ Маленькие команды (NATS легко деплоить)
✗ Когда нужна гарантия доставки на 100% → используй RabbitMQ ✗ Когда нужна история всех сообщений → используй Kafka ✗ Когда требуется транзакционность → используй RabbitMQ
Развёртывание
# Docker
docker run -d -p 4222:4222 nats
# Kubernetes
helm repo add nats https://nats-io.github.io/k8s/helm/charts/
helm install nats nats/nats
# Локально
nats-server
Преимущества и недостатки
Преимущества:
- Очень быстро: 1+ миллион сообщений в секунду
- Простая инсталляция и конфигурация
- Минимум ресурсов (100-200 MB для сервера)
- Встроенная безопасность (TLS, auth)
- Легко масштабируется
Недостатки:
- Без гарантии доставки в базовом режиме
- Нет UI для управления (только CLI)
- Сообщения в памяти (потеря при перезагрузке без JetStream)
- Меньше экосистемы чем RabbitMQ/Kafka
Вывод
NATS — это отличный выбор для микросервисных архитектур, где нужна низкая задержка и простота. Если твои микросервисы часто общаются друг с другом и нужна скорость — NATS будет быстрее и проще чем RabbitMQ. С JetStream получаешь гарантии доставки и при этом остаёшься быстрым. Это инструмент для тех, кто ценит простоту и производительность.