К основному содержимому
к выпуску
Конспект выпуска2023Fellow

Distributed Systems — выпуск 2

Второй выпуск по книге Distributed Systems разбирает главу об архитектурах. Александр и коллеги зовут в гости Алексея, архитектора инвестиционных систем, и Сергея Иванова, который проектирует распределённые системы больше двадцати лет: за час с небольшим они проходят слои и протоколы, сервис-ориентированные стили, middleware, системные архитектуры, облака, edge и блокчейн.

Code of Architecture · книжный клуб7 минут

Конспект сокращён относительно полного выпуска; примеры и оценки передают опыт и позиции участников.

Основная линия материала
01

Слои, звенья и цена уровней

Алексей рассказывает о себе: полтора года в инвестиционном направлении, где внедряет архитектурные практики и строит высоконагруженные системы для доступа клиентов к мировым рынкам, а до этого были инфраструктура, разработка ПО и видеостриминг в духе Twitch с возможностью заработка, который не взлетел. Сергей Иванов проектирует больше двадцати лет: онлайн-казино, «когда это ещё не было незаконным», банковские системы со сложным доменом, собственную инфраструктуру, которую собирали сами, во времена, когда про облака не знали; с 2019 года проводит конференцию по архитектуре и больше года назад участвовал в создании архитектурной ассоциации, где спор о том, как назвать практикующего консультанта, который в ней состоит, упёрся в одну из главных проблем разработки — именование. Книгу участники хвалят за то, что термин появляется посреди повествования и авторы ссылаются на работы, где он вводился. Минус тот же: вырвать определение из контекста трудно, и один из участников признаётся, что при конспектировании просто переписывает текст — настолько всё концентрированно.

Архитектура у авторов — это то, из каких компонентов состоит система, как они связаны и взаимодействуют; рядом стоят промежуточный слой, отделяющий приложения от нижележащих платформ, и системная архитектура, то есть развёртывание на реальных машинах, до которого, замечает один из ведущих, на систем-дизайн-интервью редко успевают дойти. Слои — разделение логическое, звенья — физическое, и определение строится на противопоставлении; те же компоненты могут ужиться в одном процессе, если приложение собрано из слабо связанных кусков с внутрипроцессным или сетевым транспортом. Слой описывается тройкой «интерфейс — сервис — протокол», пример — сетевые стеки. Плюсы: реализации взаимозаменяемы, а тестировать слои проще, чем одну огромную конструкцию. Минус — цена пересечения границ: заголовки и преобразования данных на десятке слоёв могут стоить дороже полезной работы, отсюда сжатие заголовков, буферизация и попытки вроде HTTP/2 и QUIC, плюс административная плата за поддержку каждого протокола.

02

Удалённые вызовы, микросервисы и события

Классическую трёхуровневую схему участники пролистывают — с неё все когда-то начинали — и идут в сервис-ориентированные стили, где авторы смешали объектные архитектуры, микросервисы и REST. Удалённый вызов методов вспоминают без нежности: дёргаешь локальный метод, а исполняется он на другой машине; тестовую среду под такое построить почти невозможно, задержки постоянные, и от этого великолепия быстро ушли к обмену сообщениями. Один из участников оговаривается: виноват мог быть не подход, а исполнение — middleware тогда, вероятно, писали плохо, и при хорошей реализации идея имела бы право на жизнь. Проблема, по мнению участников, в ложных гарантиях: middleware прячет и сложность, и идемпотентность вызовов, разработчик пишет код так, будто процесс падает целиком, а ждёт на порядок дольше и ловит ошибки там, где их не ждал. Ментальная модель не меняется между локальным и удалённым вызовом, поэтому даже настроить приложение нормально не выходит: непонятно, где оно стоит.

Один из ведущих связывает это с когнитивной сложностью из книги о философии дизайна ПО, которую читает параллельно: сложность, спрятанную под гарантии, прорывает в самом неудобном месте — идёшь по красивому тонкому льду, проваливаешься, тебя сносит течением, а зная про глубину, ты бы построил мост. Микросервисы участники выводят из объектно-ориентированного дизайна: композиция большого сервиса из мелких, где ключ — модульность и логические границы; сначала делили как придётся, а когда стало тяжело, на помощь пришёл DDD. В книге про них всего один блок, зато по делу: соглашения о размере нет, важны отдельные процессы, возможно на разных машинах, и независимость сервисов. Претензия к главе тоже есть — REST вынесен отдельным стилем, хотя микросервис спокойно отдаёт и RPC, и REST; сам REST хвалят за понятный человеку набор ресурсов и операций и за то, что состояние хранит клиент. Оттуда же и клиентские композиции: главным потребителем стал человек, а не компьютер.

03

Middleware, звенья, облака и блокчейн

Таблица связанности раскладывает взаимодействие по ссылочной и временной осям: прямой вызов связан по обеим, почтовый ящик конкретного получателя развязывает время, событийная шина — ссылку, а самый развязанный угол — разделяемое пространство данных, для которого приводят бытовой пример с файловой шарой, куда коллеги складывают файлы и раз в день заглядывают. Подписка бывает по топику, по ключу и по содержимому: в книге подписываются на события с координатами внутри географической области, а рабочий пример звучит из инвестиций — событие «портфель обновлён», и сервис сам решает, интересны ли ему облигации или акции. Тут же вспоминают техническое ограничение популярных брокеров: топик на каждого из трёх миллионов клиентов физически не заведёшь, поэтому приложения читают весь поток и проверяют каждое событие. Middleware авторы описывают как операционную систему распределённой системы: управление ресурсами, общение приложений, безопасность и учёт потреблённых ресурсов. Расширяют middleware обёртками и перехватчиками: обёртки между всеми парами приложений дают полносвязный граф, который замучаешься писать, брокер сводит схему к звезде, а современный пример перехвата — service mesh, который берёт на себя безопасное взаимодействие и обнаружение сервисов и умеет, например, взаимную аутентификацию по доверенным ключам.

В системных архитектурах авторы разделяют вертикальное деление по функциям и горизонтальное, где ноды одинаковы, но держат разные части данных — как разнесение столбцов против шардирования в базах. Классических звеньев три, но в жизни доходит до восьми-девяти: клиентский запрос в инвестициях проходит миллион приложений и транспортов по пути к бирже. Симметричные сети, где узел одновременно клиент и сервер, разделяют на структурированные, чья топология требует администратора, и неструктурированные, которые живут на нестабильном составе и распространении через gossip. Последнюю треть проходят бегом: облако даёт пул ресурсов и эластичность, но остаются вопросы цены, гарантий и мощностей в нужном регионе, а сервисы лучше брать с ванильной установкой; edge придвигает вычисления к клиенту, где сотня миллисекунд задержки для беспилотника уже критична, а Amazon готов привезти стойки прямо к заказчику; в блокчейне участники подчёркивают неизменяемость цепочки — и вспоминают, как в Google File System изменяемые чанки на границе разных мастеров заставляли делать распределённые транзакции, а в Colossus их сделали неизменяемыми.

Выводы

Что стоит унести с собой

  1. 01Слои — разделение логическое, звенья — физическое; взаимозаменяемость и простота тестирования оплачиваются заголовками, а на десятке слоёв пересечение границ дороже полезной работы.
  2. 02Удалённый вызов, притворяющийся локальным, даёт ложные гарантии: ментальная модель не меняется, идемпотентность спрятана в middleware, а ошибки и задержки приходят там, где их не ждут.
  3. 03Про микросервисы в книге одна страница, но по делу: соглашения о размере нет, важны отдельные процессы и независимость, а логические границы помогает найти DDD.
  4. 04Неизменяемость упрощает распределённый дизайн: в Google File System изменяемые чанки на границе разных мастеров требовали распределённых транзакций, в Colossus чанки сделали неизменяемыми.

Источники