Памятка по системному дизайну

Выбор правильной архитектуры = Выбор правильных сражений + Управление компромиссами

Перевод: https://gist.github.com/vasanthk/485d1c25737e8e72759f

Основные шаги

  1. Уточнить и согласовать масштаб системы
  • Варианты использования (описание последовательностей событий, которые в совокупности приводят к полезному действию системы)
  • Кто будет использовать систему?
  • Как они будут ее использовать?
  1. Ограничения
  • В основном определите ограничения по обработке трафика и данных в масштабе.
  • Масштаб системы (запросы в секунду, типы запросов, объем записываемых данных в секунду, объем считываемых данных в секунду)
  • Особые системные требования, такие как многопоточность, ориентация на чтение или запись.
  1. Проектирование архитектуры высокого уровня (абстрактный дизайн)
  • Набросайте важные компоненты и связи между ними, не вдаваясь в детали.
  • Уровень сервиса приложений (обслуживает запросы)
  • Перечислите различные необходимые сервисы.
  • Уровень хранения данных
  • Например, масштабируемая система обычно включает веб-сервер (балансировщик нагрузки, load balancer), сервис (разделение сервисов, service partition), базу данных (кластер баз данных master/slave) и системы кэширования.
  1. Проектирование компонентов
  • Компоненты + конкретные API, необходимые для каждого из них.
  • Объектно-ориентированный дизайн для функциональности.
  • Сопоставление функций с модулями: один сценарий для одного модуля.
  • Рассмотрите отношения между модулями:
    • Некоторые функции должны иметь уникальный экземпляр (Одиночки, Singletons)
    • Основной объект может состоять из многих других объектов (композиция, composition)
    • Один объект является другим объектом (наследование, inheritance)
  • Проектирование схемы базы данных.
  1. Понимание узких мест
  • Возможно, вашей системе нужен балансировщик нагрузки и множество машин за ним для обработки пользовательских запросов.
  • Или, возможно, данных так много, что вам нужно распределить базу данных на несколько машин. Каковы некоторые недостатки, возникающие при этом?
  • Слишком ли медленная база данных и нуждается ли она в кэшировании в памяти?
  1. Масштабирование абстрактного дизайна
  • Вертикальное масштабирование (vertical scaling)
    • Масштабирование путем добавления большей мощности (CPU, RAM) к существующей машине.
  • Горизонтальное масштабирование (horizontal scaling)
    • Масштабирование путем добавления большего количества машин в пул ресурсов.

Кэширование (Caching)

Балансировка нагрузки помогает масштабироваться горизонтально на постоянно растущем числе серверов, но кэширование позволит вам гораздо эффективнее использовать уже имеющиеся ресурсы, а также сделает возможными иначе недостижимые требования к продукту.

  • Кэширование приложений требует явной интеграции в код приложения. Обычно оно проверяет, есть ли значение в кэше; если нет, извлекает значение из базы данных.
  • Кэширование базы данных, как правило, «бесплатно». Когда вы включаете базу данных, вы получаете некоторый уровень настройки по умолчанию, который обеспечит определенную степень кэширования и производительности.
  • Кэши в памяти (in-memory caches) наиболее мощны с точки зрения чистой производительности. Это потому, что они хранят весь набор данных в памяти, а доступ к RAM на порядки быстрее, чем к диску. Например, Memcached или Redis.

Примеры:

  • Предварительный расчет результатов (например, количество посещений с каждого реферального домена за предыдущий день)
  • Предварительное создание дорогостоящих индексов (например, предлагаемые истории на основе истории кликов пользователя)
  • Хранение копий часто запрашиваемых данных в более быстром бэкенде (например, Memcache вместо PostgreSQL)

Балансировка нагрузки (Load balancing)

Публичные серверы масштабируемого веб-сервиса скрыты за балансировщиком нагрузки. Этот балансировщик нагрузки равномерно распределяет нагрузку (запросы от ваших пользователей) на вашу группу/кластер серверов приложений.

Типы:

  • Умный клиент (трудно сделать идеально)
  • Аппаратные балансировщики нагрузки (дорого, но надежно)
  • Программные балансировщики нагрузки (гибридные — подходят для большинства систем)

Репликация базы данных (Database replication)

Репликация базы данных — это частое электронное копирование данных из базы данных на одном компьютере или сервере в базу данных на другом, чтобы все пользователи имели доступ к одному уровню информации. Результатом является распределенная база данных, в которой пользователи могут получить доступ к данным, относящимся к их задачам, не мешая работе других. Реализация репликации базы данных с целью устранения неоднозначности или несогласованности данных между пользователями известна как нормализация.

Партиционирование базы данных (Database partitioning)

Партиционирование реляционных данных обычно относится к разложению ваших таблиц либо по строкам (горизонтально), либо по столбцам (вертикально).

Map-Reduce

Для достаточно небольших систем вы часто можете обойтись специальными запросами к SQL-базе данных, но этот подход может не масштабироваться тривиально, когда количество хранимых данных или нагрузка на запись требует шардинга вашей базы данных, и обычно требует выделенных подчиненных узлов для выполнения этих запросов (в этот момент, возможно, вы предпочтете использовать систему, разработанную для анализа больших объемов данных, вместо борьбы с вашей базой данных).

Добавление слоя map-reduce позволяет выполнять интенсивные операции с данными и/или обработкой за разумное время. Вы можете использовать его для расчета предлагаемых пользователей в социальном графе или для создания аналитических отчетов. Например, Hadoop, и, возможно, Hive или HBase.

Платформенный слой (Сервисы) (Platform Layer (Services))

Разделение платформы и веб-приложения позволяет масштабировать части независимо. Если вы добавляете новый API, вы можете добавить серверы платформы без добавления ненужной мощности для уровня веб-приложения.

Добавление платформенного слоя может быть способом повторного использования вашей инфраструктуры для нескольких продуктов или интерфейсов (веб-приложение, API, приложение для iPhone и т.д.) без написания слишком большого количества избыточного шаблонного кода для работы с кэшами, базами данных и т.д.

Ключевые темы для проектирования системы

  1. Параллелизм (Concurrency)
  • Понимаете ли вы потоки, взаимоблокировку и голодание? Знаете ли вы, как распараллеливать алгоритмы? Понимаете ли вы согласованность и когерентность?
  1. Сетевое взаимодействие (Networking)
  • Примерно понимаете ли вы IPC и TCP/IP? Знаете ли вы разницу между пропускной способностью и задержкой, и когда каждый фактор является релевантным?
  1. Абстракция (Abstraction)
  • Вы должны понимать системы, на которых вы строите. Знаете ли вы примерно, как работают ОС, файловая система и база данных? Знаете ли вы о различных уровнях кэширования в современной ОС?
  1. Производительность в реальном мире (Real-World Performance)
  • Вы должны быть знакомы со скоростью всего, что может делать ваш компьютер, включая относительную производительность RAM, диска, SSD и вашей сети.
  1. Оценка (Estimation)
  • Оценка, особенно в форме приблизительного расчета, важна, потому что она помогает вам сузить список возможных решений только до тех, которые осуществимы. Тогда вам нужно написать только несколько прототипов или микро-бенчмарков.
  1. Доступность и надежность (Availability & Reliability)
  • Думаете ли вы о том, как вещи могут выйти из строя, особенно в распределенной среде? Знаете ли вы, как проектировать систему для борьбы с сетевыми сбоями? Понимаете ли вы долговечность?

Соображения по проектированию системы веб-приложений:

  1. Безопасность (CORS)
  2. Использование CDN
  • Сеть доставки контента (CDN) — это система распределенных серверов (сеть), которая доставляет веб-страницы и другой веб-контент пользователю на основе географического расположения пользователя, происхождения веб-страницы и сервера доставки контента.
  • Эта услуга эффективна для ускорения доставки контента веб-сайтов с высоким трафиком и веб-сайтов с глобальным охватом. Чем ближе сервер CDN географически к пользователю, тем быстрее контент будет доставлен пользователю.
  • CDN также обеспечивают защиту от больших всплесков трафика.
  1. Полнотекстовый поиск (Full Text Search)
  • Использование Sphinx/Lucene/Solr — которые достигают быстрых поисковых ответов, потому что вместо прямого поиска по тексту они ищут по индексу.
  1. Автономная поддержка/Прогрессивное улучшение
  • Service Workers
  • Web Workers
  1. Серверный рендеринг (Server Side rendering)
  2. Асинхронная загрузка активов (Lazy load items)
  3. Минимизация сетевых запросов (Http2 + bundling/sprites и т.д.)
  4. Продуктивность разработчиков/Инструментарий
  5. Доступность (Accessibility)
  6. Интернационализация
  7. Отзывчивый дизайн (Responsive design)
  8. Совместимость браузеров

Рабочие компоненты архитектуры фронтенда

  1. Код
  • HTML5/WAI-ARIA
  • Стандарты и организация кода CSS/Sass
  • Объектно-ориентированный подход (как объекты разбиваются и собираются вместе)
  • JS фреймворки/организация/техники оптимизации производительности
  1. Доставка активов — Фронтенд операции
  2. Документация
  • Документы по внедрению
  • Руководство по стилю/Библиотека шаблонов
  • Диаграммы архитектуры (поток кода, цепочка инструментов)
  1. Тестирование
  • Тестирование производительности
  • Визуальная регрессия
  • Модульное тестирование
  • Сквозное тестирование
  1. Процесс
  • Git Workflow
  • Управление зависимостями (npm, Bundler, Bower)
  • Системы сборки (Grunt/Gulp)
  • Процесс развертывания
  • Непрерывная интеграция (Travis CI, Jenkins)