// Python Dev
RabbitMQ как мост между внешним и внутренним контуром
Опубликовано 03.04.2026
Брокеры очередей обычно воспринимаются как инструмент внутри одной системы — развязать микросервисы, сгладить пики нагрузки, организовать фоновые задачи. Но есть куда менее очевидное применение: использовать брокер как точку доступа к данным, которые физически находятся внутри организации и наружу не выходят.
На практике любая попытка дать внешний доступ к внутренним данным быстро превращается в инфраструктурный проект: согласования, безопасность, сетевые ограничения. Даже простая задача вроде «получить баланс клиента» может упереться в недели работы и участие нескольких команд.
Данные внутри, запрос снаружи
Типичная ситуация: есть внешнее приложение — личный кабинет, мобильное приложение или партнёрский сервис — которому нужно получить актуальные данные из внутренней системы. Например, баланс клиента из биллинга.
Стандартные варианты здесь один хуже другого. Открыть порт наружу — самый очевидный, который первым же и отклоняют безопасники, и правильно делают. Поднять VPN — звучит разумно, но на практике это отдельный проект со своими согласованиями, сертификатами и поддержкой, и далеко не всегда возможный на стороне внешней системы, особенно если это чужое облако. Белый IP — его может просто не быть: провайдер даёт динамику за NAT, и пробросить соединение снаружи внутрь без дополнительной инфраструктуры невозможно. Для небольших компаний и филиалов это совершенно обычная ситуация.
Реальный кейс
В одном из проектов нужно было реализовать Telegram-бота для провайдера, через которого пользователь мог посмотреть текущий баланс. Проблема в том, что биллинг-система находилась в закрытом контуре внутри датацентра и имела SOAP API, доступный только изнутри сети. Открывать доступ наружу было запрещено, VPN на стороне бота реализовать невозможно, а сам бот работал в облаке. В итоге даже простой запрос «показать баланс» превращался в задачу интеграции между полностью изолированными системами.
Брокер снаружи как точка встречи
Идея простая, но неочевидная: поднять инстанс RabbitMQ не внутри организации, а снаружи — рядом с внешним приложением, на публично доступном сервере. Этот брокер одновременно доступен и внешней системе, и внутренней — потому что внутренний сервис сам инициирует исходящее соединение наружу, а исходящие соединения, в отличие от входящих, почти никогда не блокируются файрволом или NAT.
Схема получается такая: внешнее приложение кладёт запрос в очередь на брокере. Сервис внутри организации слушает эту очередь, забирает запрос, идёт в биллинг или любой другой внутренний источник, и кладёт ответ в другую очередь. Внешнее приложение забирает ответ.
Данные попадают наружу ровно тогда, когда они нужны, и только те, которые были запрошены. Внутренняя система остаётся закрытой — она сама решает, когда и что отдавать.
RPC поверх очередей: асинхронность без боли
Очевидная сложность такой схемы — асинхронность. Когда запросов много, нужно понимать, какой ответ относится к какому запросу. Можно маркировать каждое сообщение вручную, но RabbitMQ предоставляет готовый механизм — RPC поверх очередей.
Работает это так: клиент при отправке запроса указывает имя временной очереди, на которую ждёт ответ (reply_to), и уникальный correlation_id. Внутренний сервис обрабатывает запрос и отправляет ответ не в общую очередь, а напрямую на эту временную очередь с тем же correlation_id. Клиент просто ждёт своего ответа — без лишней логики маршрутизации.
Реализовывать это руками необязательно — RPC поверх RabbitMQ уже поддерживают готовые библиотеки. Например, FastStream предоставляет удобный декларативный интерфейс: подписчик на очередь описывается как обычная async-функция, а механизм reply_to и correlation_id библиотека берёт на себя. Код становится компактнее и читается как обычный сервис, а не как работа с брокером напрямую.
Ниже — минимальный пример на pika, чтобы было понятно, что происходит под капотом.
Клиент (внешняя система)
import pika, uuid
connection = pika.BlockingConnection(pika.ConnectionParameters('broker.example.com'))
channel = connection.channel()
# Временная очередь для ответа — RabbitMQ сам её удалит после отключения
result = channel.queue_declare(queue='', exclusive=True)
reply_queue = result.method.queue
correlation_id = str(uuid.uuid4())
channel.basic_publish(
exchange='',
routing_key='billing.requests',
properties=pika.BasicProperties(
reply_to=reply_queue,
correlation_id=correlation_id,
),
body='{"client_id": 42, "action": "get_balance"}'
)
# Ждём ответа именно на наш запрос
for method, props, body in channel.consume(reply_queue):
if props.correlation_id == correlation_id:
print(f"Баланс: {body.decode()}")
channel.cancel()
break
Обработчик (внутренний сервис)
import pika, json
connection = pika.BlockingConnection(pika.ConnectionParameters('broker.example.com'))
channel = connection.channel()
channel.queue_declare(queue='billing.requests')
def on_request(ch, method, props, body):
request = json.loads(body)
balance = get_balance_from_billing(request['client_id']) # обращение к внутреннему источнику
ch.basic_publish(
exchange='',
routing_key=props.reply_to,
properties=pika.BasicProperties(correlation_id=props.correlation_id),
body=str(balance)
)
ch.basic_ack(delivery_tag=method.delivery_tag)
channel.basic_consume(queue='billing.requests', on_message_callback=on_request)
channel.start_consuming()
Это превращает асинхронное взаимодействие в почти синхронное с точки зрения кода: отправил запрос — подождал — получил ответ. При этом никакого дополнительного состояния хранить не нужно.
Что в итоге
Такая схема закрывает сразу несколько проблем без лишней инфраструктуры: не нужен белый IP, не нужен VPN, не нужно открывать доступ во внутренний контур. Авторизация и шифрование решаются на уровне RabbitMQ — TLS и credentials заменяют всю инфраструктуру API-ключей и токенов. Развернуть это можно за день-два: два небольших сервиса и один инстанс брокера.
Это не универсальный инструмент. Но в задачах, где нужно дать доступ к данным из закрытого контура по запросу — биллинг, внутренние CRM, учётные системы — это один из самых простых и дешёвых вариантов. Для потоковой передачи больших объёмов или сценариев с жёсткими требованиями по задержке схема подходит хуже — там уже нужны другие инструменты.
// Python Dev
Другие статьи Python Dev
2026-04-01
Как организовать обзвон очереди через SIP и Python
Заметка разбирает архитектуру автоматического обзвона: как организован конвейер обработки, как работает дозвон через Asterisk AMI и как замыкается цикл от …
2026-04-01
Как анализировать тысячи отзывов на Wildberries с помощью LAG: пошаговый разбор
У популярных товаров на Wildberries количество отзывов легко переваливает за тысячи. Читать их вручную — долго, утомительно и неэффективно. В отзывах скрыты …
// Python Projects
Проекты Python Dev
2026-03-26
Телеграм-бот для голосовых розыгрышей
Доработка существующего Telegram-бота: звонки через SIP и Telegram, запись ответа пользователя и монетизация через Telegram Stars.
2026-03-26
Система автоматического контроля энергопотребления
MVP-система для контроля лимитов энергопотребления на точках зарядки электромобилей с автоматическим отключением реле и журналированием действий.
2026-03-26
Автоматическое ведение сети Telegram-каналов для турагента
Система автоматического ведения 150 Telegram-каналов с подбором туров и авиабилетов, генерацией визуалов и публикацией по расписанию.
// Contact
Нужна помощь?
Свяжись со мной и я помогу решить проблему