Разработка надёжной, масштабируемой и эффективной системы может оказаться довольно сложным делом. Однако понимание основных принципов и компонентов этого процесса может сделать его более управляемым. В статье рассмотрим основные компоненты в проектировании систем: DNS, балансировка нагрузки, API-шлюз и другие. Также предоставим краткую схему, которая поможет разработчикам проектировать системы разной сложности. Содержание: Схема проектирования системы Принципы проектирования систем Модульность Абстракция Разбиение на слои Масштабируемость Производительность Безопасность Отказоустойчивость и способность к восстановлению Ключевые компоненты проектирования систем DNS (система доменных имен) Балансировка нагрузки API-шлюз Сеть доставки контента (CDN) Очередь сообщений Коммуникационные протоколы Кэш База данных Техники репликации Распределенная генерация уникальных идентификаторов Загрузка видео и изображений по чанкам с помощью подписанных URL-адресов Что такое подписанные URL-адреса? Чанковая загрузка Комбинирование подписанных URL-адресов и чанковой загрузки Протоколы чата и потоковой передачи данных RTMP (Real-Time Messaging Protocol) WebRTC (Web Real-Time Communication) WebSocket SSE (Server-Sent Events) HTTP Short Polling HTTP Long Polling Вебхуки Stream API Стандартные компоненты при проектировании системы Платежный сервис Сервис аналитики Сервисы уведомлений Поисковые сервисы Служба рекомендаций Передовые практики системного проектирования Сбор требований Шаблоны проектирования Документация Итеративное проектирование Тестирование и валидация Заключение А вот наглядная схема.  С ней разработчик всегда сможет быстро освежить в памяти ключевые принципы и методы проектирования систем. Схема охватывает такие темы, как DNS, балансировка нагрузки, API-шлюз, обработка видео и изображений, кэширование, базы данных, генерация уникальных идентификаторов.  Также указаны стандартные компоненты системы, такие как сервисы платежей и рекомендаций, протоколы чата и потоковой передачи данных. Имея под рукой эту схему, вам будет проще проектировать и внедрять масштабируемые, эффективные и надежные системы. Ссылка на полное изображение Разделение системы на более мелкие, управляемые модули помогает снизить ее сложность, улучшить удобство обслуживания и возможности повторного использования. Чтобы упростить сложные системы, можно скрыть подробности их реализации и демонстрировать только основные функции. Такой подход также способствует модульности. Распределение системы по слоям, каждый из которых содержит определенный набор функций, помогает адресно работать с проблемами и улучшает удобство обслуживания. Проектирование системы с учетом возрастания нагрузки на нее. С возросшей нагрузкой можно справляться добавлением дополнительных ресурсов (горизонтальное масштабирование) или оптимизацией мощности системы (вертикальное масштабирование). Оптимизация времени отклика, пропускной способности и использования ресурсов — все это важно учитывать для проектирования эффективной системы. Чтобы обеспечить конфиденциальность, целостность и доступность системы, нужно внедрять соответствующие инструменты обеспечения безопасности. Проектирование систем, которые устойчивы к сбоям и могут восстанавливаться после ошибок. DNS — это иерархическая и децентрализованная система именования компьютеров, сервисов или других ресурсов, подключенных к Интернету или частной сети. Она переводит понятные человеку доменные имена (например, www.example.com) в IP-адреса, делая доступ к веб-сайтам и сервисам более удобным. Подробнее: Масштабирование приложений за счет оптимизации конфигурации DNSScale Applications by optimizing DNS Configuration Балансировка нагрузки — это распределение сетевого трафика между несколькими серверами, чтобы ни один не был перегружен. Такой подход повышает доступность, надежность и производительность системы. Примеры стандартных алгоритмов балансировки нагрузки — Round Robin, Least Connections и IP Hash. Подробнее: Всё о балансировщике нагрузки с Cheat SheetEverything about Load Balancer with Cheat Sheet API-шлюз — это сервер-посредник между клиентами и микросервисами в распределенной системе. Он управляет запросами и маршрутизирует их, обеспечивает соблюдение политик безопасности, а также может предоставлять дополнительные функции, такие как кэширование, ведение журнала и мониторинг. CDN — это распределенная по разным локациям сеть серверов. С ее помощью пользователи получают контент с меньшей задержкой и большей пропускной способностью. CDN кэширует контент на периферийных серверах, которые находятся близко к конечным пользователям. Эта сеть повышает производительность системы и снижает нагрузку на сервер-источник.  Подробнее: Руководство для начинающих по CDN: что это такое и как это работаетA Beginner’s Guide to CDN: What it is and How it Works Сообщения временно хранятся в очереди, чтобы облегчить взаимодействие между компонентами распределенной системы. Также эта очередь обеспечивает асинхронную обработку компонентов и помогает разделять их. Это позволяет улучшить масштабируемость и отказоустойчивость системы.  Подробнее: Все о распределённой очереди сообщенийEverything about Distributed Message Queue При разработке систем используются различные коммуникационные протоколы, такие как HTTP/HTTPS, WebSocket и gRPC. У каждого из них есть свои преимущества и недостатки. Поэтому при выборе нужно учитывать важные для вас моменты, такие как задержка, безопасность и требования к передаче данных. Кэширование — это метод временного хранения копий данных. Он позволяет быстрее находить эти данные при последующих запросах. Кэширование помогает снизить задержку, нагрузку на сервер и потребление полосы пропускания. Примеры популярных подходов в этой области включают кэширование в памяти, распределенное и браузерное кэширование.  Подробнее: Полное руководство по распределенному кэшированиюA Comprehensive Guide to Distributed Caching Выбор подходящей базы данных для системы зависит от таких факторов, как структура, масштабируемость и согласованность данных, а также задержка в доступе к ним. К распространенным типам решений относятся реляционные базы данных (например, MySQL, PostgreSQL), базы данных NoSQL (например, MongoDB, Cassandra) и базы данных NewSQL (например, Cockroach DB, Google Spanner). Репликация — это сохранение нескольких копий данных на разных узлах системы для повышения ее надежности, доступности и отказоустойчивости. Примеры стандартных подходов включают синхронную, асинхронную и полусинхронную репликацию. Создание уникальных идентификаторов в распределенной системе может быть сложной задачей, но ее нужно решить, чтобы поддерживать согласованность и целостность данных.  Подробнее: 7 известных подходов к созданию распределенного ID со сравнительной таблицей7 Famous Approaches to Generate Distributed ID with Comparison Table В этом разделе мы рассмотрим, как загружать большие файлы видео и изображений частями с помощью подписанных URL-адресов. Этот метод может повысить эффективность и надежность загрузки файлов, особенно в случаях с плохим подключением к сети. Это специальные URL-адреса, которые предоставляют временный безопасный доступ к определенному ресурсу. Например, к объекту в облачном хранилище. Эти URL содержат сигнатуру аутентификации, которая позволяет пользователю выполнить определенное действие. Например, загрузить или скачать файл в течение ограниченного периода времени. Популярные провайдеры облачных хранилищ, такие как Amazon S3 и Google Cloud Storage, позволяют создавать подписанные URL-адреса. Вот пример того, как может выглядеть подписанный URL: Загрузка больших файлов за один запрос может привести к тайм-аутам, большому расходу памяти и повышенному риску сбоев из-за нестабильности сети. Чтобы решить эту проблему, большие файлы разбивают на мелкие фрагменты и загружают их последовательно или параллельно. Такой подход повышает эффективность и надежность загрузки. Он известен как «чанковая» загрузка или загрузка «по частям». Чтобы загружать видео и изображения частями, используя подписанные URL-адреса, выполните следующие действия: Разделите файл на чанки. Разделите большой файл на мелкие фрагменты на стороне клиента. Обычно это делается с помощью JavaScript. Размер чанка может варьироваться, но для оптимальной загрузки важно добиться баланса между количеством запросов и размером каждого чанка. Запросите подписанные URL для каждого чанка. Отправьте на ваш сервер запрос для создания подписанных URL. Сервер должен создать подписанный URL с соответствующими разрешениями и временем действия и вернуть его клиенту. Загрузите чанки с помощью подписанных URL-адресов. Загрузите чанки в облачное хранилище. В зависимости от желаемого уровня параллелизма и условий сети эти загрузки могут выполняться последовательно или параллельно. Подтвердите успешную загрузку и выполните сборку. Как только все чанки будут загружены, сообщите об этом серверу, чтобы подтвердить завершение загрузки. После этого сервер может собрать фрагменты в исходный файл, а также выполнить дополнительную обработку или проверку. Обработайте неудачные загрузки. Если какой-либо чанк не будет загружен, повторите попытку, используя новый подписанный URL-адрес. Или примените свою стратегию обработки ошибок, чтобы обеспечить бесперебойную работу. Используя подписанные URL-адреса и чанковую загрузку, разработчики могут эффективно и безопасно обрабатывать большие видео и изображения, а также повышать надежность и производительность своих систем. В этом разделе мы рассмотрим протоколы чата и потоковой передачи, которые обеспечивают связь в реальном времени и потоковую передачу данных между клиентами и серверами. Понимание этих протоколов поможет разработчикам создавать интерактивные и отзывчивые приложения. RTMP — это запатентованный протокол Adobe Systems. Он нужен для потоковой передачи аудио, видео и данных через Интернет, широко используется в приложениях для потоковой передачи видео и обеспечивает низкую задержку при передаче данных между клиентами и серверами. Однако из-за зависимости от Flash Player его популярность в последние годы снизилась. на момент перевода, 26.06.2022, Flash Player уже не используется и не поддерживается — прим. переводчика WebRTC — это проект с открытым исходным кодом, который обеспечивает передачу аудио, видео и данных в реальном времени в браузерах и мобильных приложениях. Он поддерживает одноранговые соединения, снижает задержку и нагрузку на сервер. WebRTC широко используется в видеоконференциях, онлайн-играх и других приложениях, требующих связи в реальном времени. WebSocket — это коммуникационный протокол, который обеспечивает двунаправленную, полнодуплексную связь между клиентом и сервером через одно долговременное соединение. Благодаря низкой задержке и эффективным коммуникационным возможностям WebSocket часто используется в приложениях с передачей данных в реальном времени. Например, в чатах и сервисах уведомлений. Server-Sent Events (SSE) — это технология, которая позволяет серверам получать данные о клиентских событиях через HTTP-соединение. Она предназначена для односторонней связи от сервера к клиенту в реальном времени, что делает ее подходящим решением для приложений, работающих с новостными лентами и уведомлениями. В случае с Short Polling клиенты неоднократно отправляют HTTP-запросы на сервер, чтобы проверить наличие новых событий. Несмотря на простоту реализации метода, он может привести к высокой нагрузке на сервер и увеличению задержки из-за постоянных запросов, особенно если новые события происходят нечасто. Это улучшенный вариант Short Polling: клиент посылает запрос на сервер, а сервер держит его открытым до получения новых данных. Такой подход снижает количество запросов и нагрузку на сервер, однако он все же может приводить к задержкам и требует тщательного управления ресурсами сервера. Вебхуки — это определяемые пользователем HTTP-коллбеки, запускаемые в результате определенных событий в системе. Когда происходит событие, сайт-источник отправляет HTTP-запрос на URL, настроенный для вебхука. Этот подход позволяет обеспечить эффективное, привязанное к событиям взаимодействие между разными системами или сервисами. Stream API позволяет клиентам получать непрерывный поток данных с сервера, часто с помощью соединения по HTTP или WebSocket. Эти API предназначены для приложений, которым нужно получать данные в реальном времени. Например, это актуально для лент социальных сетей, данных фондового рынка и аналитики в реальном времени. Понимая и используя эти протоколы чата и потоковой передачи данных, разработчики могут создавать приложения с быстрым откликом на действия пользователя и передачей данных в реальном времени. В этом разделе мы рассмотрим некоторые стандартные компоненты, часто встречающиеся в современных системах. Понимание этих компонентов поможет разработчикам легко интегрировать их в свои системы и повышать их общую функциональность. Платежные сервисы обрабатывают транзакции между клиентами и компаниями. Для сервисов электронной коммерции и платформ, основанных на подписке, критически важно интегрировать надежный платежный сервис. Примеры популярных сервисов: Stripe, PayPal и Square. Обычно они предоставляют API для обеспечения безопасности транзакций и управления повторяющимися платежами, возвратами и т. п. Сервисы аналитики позволяют собирать, обрабатывать и визуализировать данные, помогая компаниям принимать взвешенные решения. Они могут отслеживать поведение пользователей, контролировать производительность системы и анализировать тенденции. Примеры таких сервисов — это Google-Analytics, Mixpanel и Amplitude. Интеграция сервисов аналитики в систему поможет компаниям оптимизировать свои предложения и улучшить клиентский опыт. Сервисы уведомлений информируют пользователей о новостях, событиях и другой важной информации. Эти сервисы могут доставлять уведомления по почте, SMS, отправлять push-уведомления.  Примеры сервисов: Firebase Cloud Messaging (FCM), Amazon Simple Notification Service (SNS) и Twilio. Мощная поисковая система необходима для систем с большим объемом данных или контента. Она должна быть масштабируемой и обеспечивать быстрый и релевантный поиск. Примеры поисковых сервисов — Elasticsearch, Apache Solr и Amazon CloudSearch. Обычно они поддерживают фильтры, полнотекстовый и фасетный поиск. Это позволяет пользователям находить нужную информацию быстро и эффективно. Сервисы рекомендаций показывают пользователям персонализированные предложения на основе их предпочтений, поведения и других факторов. Они могут значительно повысить вовлеченность и удовлетворенность пользователей. Методы создания рекомендаций включают коллаборативную и контентную фильтрацию, а также гибридные подходы. Для создания более сложных рекомендаций также можно использовать алгоритмы машинного обучения, такие как матричная факторизация и глубокое обучение. Включая эти стандартные компоненты в свои системы, разработчики могут повысить функциональность приложений и улучшить клиентский опыт. Тщательно изучите и задокументируйте требования к системе перед началом проектирования. Используйте проверенные шаблоны для решения повторяющихся проблем и улучшения общей архитектуры. Документируйте свои решения, предположения и обоснования в рамках проекта, чтобы улучшить взаимодействие с заинтересованными сторонами и повысить удобство обслуживания системы. Доработайте свой проект в рамках нескольких итераций и циклов обратной связи. Позвольте ему расти и развиваться. Проверьте соответствие вашего проекта требованиям и проведите тестирование для выявления и устранения потенциальных проблем. Проектирование системы — многогранный и сложный процесс, требующий глубокого понимания разных компонентов, протоколов и методов. В статье мы рассмотрели такие темы, как DNS, балансировка нагрузки, API-шлюзы, обработка видео и изображений, кэширование, базы данных, генерация уникальных идентификаторов, стандартные компоненты, такие как сервисы платежей и рекомендаций, а также протоколы чата и потоковой передачи данных. Используя эти знания, разработчики могут создавать масштабируемые, эффективные и надежные системы, которые отвечают поставленным требованиям и обеспечивают бесперебойную работу пользователей. Важно помнить, что проектирование системы — итерационный процесс, и для создания и поддержки успешных приложений нужно постоянное совершенствование. Разработчик, который понимает рассмотренные выше концепции и важность адаптивности, может уверенно проектировать и внедрять надежные системы. Перевод подготовлен KTS. Другие наши статьи и переводы по бэкенду и асинхронному программированию для начинающих: Цикл статей «Первые шаги в aiohttp»: пишем первое hello-world-приложение, подключаем базу данных, выкладываем проект в Интернет Визуализация 5 алгоритмов сортировки на Python Разбираемся в асинхронности: где полезно, а где — нет? Другие наши статьи по бэкенду и асинхронному программированию для продвинутого уровня: Пишем свой Google, или асинхронный краулер с rate limits на Python Пишем асинхронного Телеграм-бота Пишем Websocket-сервер для геолокации на asyncio  Backend разработчик