вторник, 15 сентября 2026 г.

Gonchar, Gemini, Giga, Architecture, Declarative, Aspire, Router

Gonchar, Gemini, Giga,

Architecture, Declarative, Aspire, Router

Архитектура системы: Декларативная федерация (Declarative Federation)

Код как конституция (Закон AppHost)

В современной среде .NET Aspire архитектура системы перестает быть просто абстрактной схемой в Visio; она становится исполняемым физическим законом. Проект AppHost берет на себя роль управляющего слоя (Control Plane), который жестко диктует правила взаимодействия в системе.

• Zero Trust по умолчанию (Нулевое доверие): Микросервисы изначально изолированы. Они физически неспособны обнаружить друг друга в сети или вызвать соседний API, пока им не будет выдано явное разрешение в коде через метод конфигурации .WithReference().

• Буфер гравитации (The Gravity Buffer): Вся сложность сетевых взаимодействий замыкается на центральном Маршрутизаторе/Шлюзе (например, реализованном на базе библиотеки Wolverine). Он принудительно внедряет топологию «Звезда» (Hub-and-Spoke), где шлюз — это центр, а сервисы — лучи. Это предотвращает превращение системы в «Спагетти-архитектуру» (Spaghetti Mesh), где каждый сервис связан с каждым, порождая неуправляемую паутину из \(N \times N\) соединений.

________________________________________

Синхронная агрегация и асинхронные мутации (Sync Aggregation & Async Mutation)

Центральный маршрутизатор выполняет роль гибридного BFF (Backend-for-Frontend), разделяя потоки данных по принципу CQRS (разделение чтения и записи):

• Чтение / Запросы (Отображение UI-дашбордов): Для получения данных используется паттерн API Composition (Композиция API). Маршрутизатор выполняет веерную рассылку (fan-out) запросов к внутренним микросервисам через быстрый бинарный протокол gRPC. Данные собираются воедино без лишних затрат ресурсов на сериализацию и десериализацию (в отличие от классического текстового JSON).

• Запись / Команды (Размещение ордеров): Обработка транзакций построена на базе Wolverine и паттерна Transactional Outbox (Внешний ящик отправки). Пользовательский интерфейс (UI) мгновенно получает ответ 202 Accepted («Принято в обработку»), что обеспечивает молниеносный отклик. В это время маршрутизатор берет на себя гарантированную асинхронную доставку команды во внутренние сервисы (выступая как Федерация сервисов), даже если в этот момент они временно отключены или перегружены.

________________________________________

Структуры данных (Data Structures)

Уровни цен (Price Levels) — Красно-черное дерево (Red-Black Tree)

Биржевой стакан (Order book) требует экстремально быстрых операций: добавления ордеров, их удаления и постоянного доступа к «верхушке стакана» — лучшим ценам покупки и продажи (best bid/ask).

Для этого уровни цен организуются в виде самобалансирующегося бинарного дерева поиска (чаще всего красно-черного), где ключом является Цена, а значением — Очередь ордеров (Price -> Queue).

• Это дает гарантированную скорость выполнения операций \(O(\log N)\) при поиске или создании новых ценовых уровней.

• Доступ к самой лучшей цене (минимальной/максимальной в дереве) занимает фиксированное время \(O(1)\).

Очереди ордеров (Order Queues) — Двусвязный список (Doubly Linked List)

Внутри каждого конкретного уровня цены все ордера выстраиваются в двусвязный список. В связке с хэш-таблицей (которая хранит прямые ссылки на узлы списка по ID ордера) это дает феноменальную скорость:

• Вставка нового ордера в конец очереди занимает \(O(1)\).

• Удаление ордера из любой части очереди (при отмене пользователем или полном исполнении) занимает \(O(1)\), так как двусвязный список позволяет мгновенно «перебросить» указатели соседних элементов без перебора всей структуры.

________________________________________

Алгоритмы мэтчинга / сведения ордеров (Matching Algorithms)

FIFO (First In, First Out — Приоритет цены и времени)

Это классический стандарт для спотовых (предметных) бирж. Если несколько ордеров находятся на одном ценовом уровне, они будут исполнены строго в том хронологическом порядке, в котором они поступили в систему. Такой подход поощряет маркетмейкеров, которые предоставляют ликвидность на ранних этапах.

• Контекст: На уровне цены $50 стоят два лимитных ордера: [Ордер А: объем 10] \(\rightarrow \) [Ордер B: объем 5].

• Входящий запрос: Рыночный ордер на покупку объема 12 по цене $50.

• Результат сведения: Ордер А исполняется полностью (забирает 10), ордер B исполняется частично (забирает оставшиеся 2), в очереди ордера B остается объем 3.

Pro-Rata (Пропорциональное распределение)

Данный алгоритм широко применяется на рынках деривативов (фьючерсов и опционов). Он полностью игнорирует время поступления заявки. Входящий объем распределяется между всеми ордерами на уровне пропорционально их размеру. Это стимулирует крупных игроков выставлять глубокую ликвидность (ордера больших объемов).

• Контекст: На уровне цены $50 стоят два ордера разного объема: [Ордер А: объем 100] (составляет 80% от общего объема уровня) и [Ордер B: объем 25] (составляет 20%).

• Входящий запрос: Рыночный ордер на покупку объема 10 по цене $50.

• Результат сведения: Время выставления не важно. Объемы распределяются согласно долям: Ордер А исполняется на 8 (80% от 10), а Ордер B исполняется на 2 (20% от 10).

________________________________________

Очереди сообщений и конкурентность (Message Queues & Concurrency)

Высокопроизводительное ядро мэтчинга (matching engine) в продакшене работает строго в один поток (Single Thread). Это позволяет полностью избавиться от накладных расходов на межпоточные блокировки (locks, mutexes) и исключает возникновение состояний гонки (race conditions). При этом данный поток жестко привязывается к выделенному изолированному ядру процессора операционной системы (CPU affinity), чтобы исключить задержки на переключение контекста.

• Входной поток (Ingress): API-шлюзы не отправляют ордера напрямую в движок. Они сбрасывают их в ультра-низколатентный последовательный конвейер — секвенсор (например, LMAX Disruptor или Aeron). Задача секвенсора — присвоить каждому входящему пакету строгий, детерминированный порядковый номер перед тем, как отдать его на обработку однопоточному движку.

• Выходной поток (Egress): Как только движок совершил сведение (мэтчинг), он не тратит время на запись в базу или отправку клиентам. События сделок и обновления стаканов асинхронно выбрасываются в сеть через UDP Multicast (или брокер Kafka). Эту информацию подхватывают дистрибьюторы рыночных данных (Market Data) и клиринговые сервисы (расчетные палаты), а критически важное ядро мэтчинга мгновенно освобождается для обработки следующего ордера.

________________________________________




Комментариев нет:

Отправить комментарий