Перейти к основному содержимому

Собеседование на Middle Go с лидом из Fivegen. Проектируем дизайн видеосервиса

· 24 мин. чтения

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

Вопрос 1. Почему вы решили заняться программированием?

Таймкод: 00:00:42

Ответ собеседника: правильный. Хотел создавать что-то новое, изначально мечтал сделать свои сервисы и сайты, любовь к созиданию подтолкнула к этому.

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

Вопрос 2. Почему выбрали работу с бэкендом, а не фронтендом?

Таймкод: 00:01:09

Ответ собеседника: правильный. Больше нравится серверная часть из-за необходимости продумывать архитектуру и потому что у него технический склад ума, а не творческий.

Правильный ответ:
Работа с серверной частью привлекает тем, что она требует глубокого понимания архитектурных решений, построения масштабируемых, отказоустойчивых и высоконагруженных систем. Задачи бэкенда включают проектирование API, работу с базами данных, оптимизацию алгоритмов, обеспечение безопасности и интеграцию с различными сервисами. Эти аспекты предполагают системное мышление, знание принципов построения распределённых систем, алгоритмов и структур данных.

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

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

Вопрос 3. Почему вы выбрали язык Go вместо Python или C++?

Таймкод: 00:02:19

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

Правильный ответ:
Go (Golang) сочетает в себе ряд преимуществ, которые делают его особенно привлекательным для разработки высокопроизводительных серверных приложений и микросервисов.

Основные причины выбора Go:

  • Простота и лаконичность синтаксиса
    Язык минималистичен, что снижает порог входа, ускоряет разработку и облегчает поддержку кода. Компилятор Go навязывает определённые стандарты оформления, что способствует единообразию кода в команде.

  • Отличная поддержка конкурентности
    Go изначально спроектирован для эффективного параллельного выполнения с помощью легковесных потоков — горутин, управляемых рантаймом. Для межгорутинного взаимодействия используются каналы (channels), что способствует написанию безопасного конкурентного кода без сложных примитивов синхронизации.
    Пример создания горутины и взаимодействия через канал:

func worker(ch chan int) {
for n := range ch {
fmt.Println("Received:", n)
}
}

func main() {
ch := make(chan int)
go worker(ch)
ch <- 42
close(ch)
}
  • Богатая и эффективная стандартная библиотека
    Go предоставляет мощный набор стандартных пакетов для работы с сетевыми протоколами, HTTP-серверами, сериализацией данных, шифрованием и др., что ускоряет старт проекта и снижает зависимость от сторонних библиотек.

  • Высокая производительность и статическая типизация
    Go компилируется в машинный код, обеспечивая хорошую производительность, сравнимую с C и C++, при этом сохраняя простоту разработки. Статическая типизация позволяет обнаруживать ошибки на этапе компиляции.

  • Удобная система сборки и деплоя
    Go компилятор создает статически связанные бинарные файлы без внешних зависимостей, что облегчает развертывание.

  • Сбалансированность между Python и C++
    Go сочетает в себе производительность C++ и простоту Python, при этом избегая сложностей обеих технологий. Python хорош для быстрого прототипирования, но уступает Go в производительности и удобстве масштабирования. C++ мощен, но сложен в разработке и сопровождении, требует управления памятью и сложной отладки.

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

Вопрос 4. Почему вы решили обучаться в школе навыков и каков ваш опыт обучения?

Таймкод: 00:03:50

Ответ собеседника: правильный. Хотел повысить грейд, изначально учился по бесплатным курсам и курсу МФТИ, затем столкнулся с потолком и решил взять менторство для ускорения роста, занимается там примерно два месяца.

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

Обучение в школе навыков с опытными наставниками помогает:

  • Получить индивидуальную оценку текущих знаний и выявить зоны для развития.
  • Ускорить рост за счёт персонализированных рекомендаций и работы над реальными кейсами.
  • Освоить продвинутые темы, которые сложно изучить самостоятельно: проектирование архитектур, оптимизация высоконагруженных систем, паттерны проектирования, лучшие практики и антипаттерны.
  • Развить инженерное мышление, умение аргументировать свои решения и проводить код-ревью.
  • Подготовиться к переходу на следующий уровень, например, для успешного прохождения интервью на более высокую позицию.
  • Получить сообщество единомышленников, обмен знаниями и опытом.

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

Вопрос 5. В какой компании вы сейчас работаете и над какими проектами?

Таймкод: 00:07:29

Ответ собеседника: правильный. Работает джуниор+ в СК Информика, занимаются системами учёта и контроля доступа для крупных мероприятий вроде форумов и выставок.

Правильный ответ:
В настоящее время ведется работа в компании, специализирующейся на разработке систем учета и контроля доступа, которые используются для крупных событий, таких как деловые форумы, выставки и конференции.

Такие проекты включают в себя:

  • Разработку серверных решений для регистрации и идентификации участников, интеграцию с внешними системами (например, CRM, системами безопасности).
  • Реализацию API для мобильных и десктопных клиентов, которые взаимодействуют с системой в реальном времени.
  • Обеспечение масштабируемости и высокой доступности сервисов, способных обслуживать тысячи пользователей одновременно.
  • Внедрение механизмов безопасности — шифрование данных, контроль авторизации и аутентификации, защита от несанкционированного доступа.
  • Обработку потоков данных с устройств контроля доступа (сканеры QR-кодов, RFID-ридеры), распределенную обработку и хранение логов посещений.
  • Аналитику данных о посещаемости и формирование отчетности для организаторов.

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

Вопрос 6. Расскажите о самой сложной или интересной задаче, которую решаете сейчас на работе.

Таймкод: 00:08:08

Ответ собеседника: правильный. Сейчас интегрирует Matrix (протокол для защищённых чатов) с Telegram-ботами и добавляет туда ИИ для автопомощи пользователям, что довольно сложно.

Правильный ответ:
Одна из сложных и интересных задач — интеграция протокола Matrix с Telegram-ботами с добавлением функциональности искусственного интеллекта для автоматизированной поддержки пользователей.

Особенности и сложности этой задачи включают:

  • Интеграция разнородных систем связи
    Matrix — это федеративный протокол для защищённых децентрализованных коммуникаций, поддерживающий сквозное шифрование. Telegram использует свои API и протоколы обмена сообщениями. Необходимо построить шлюз (bridge), обеспечивающий:

    • корректную маршрутизацию сообщений между Matrix и Telegram,
    • трансляцию форматов данных (текст, вложения, реакции),
    • сохранение контекста беседы и идентификацию участников,
    • поддержку разных типов чатов (группы, приватные, каналы).
  • Обеспечение безопасности и приватности
    Следует учитывать различия в моделях безопасности: если в Matrix реализовано сквозное шифрование, то при передаче сообщений в Telegram важно не потерять этот уровень приватности либо явно уведомлять пользователя об этом.

  • Интеграция искусственного интеллекта (ИИ)
    Добавление ИИ-агента (например, на базе LLM или специализированных NLP-моделей) для:

    • автоматического ответа на частые вопросы,
    • помощи в навигации по сервису,
    • маршрутизации запросов к оператору,
    • анализа тональности и приоритезации сообщений.
      Для этого нужно построить pipeline обработки сообщений:
func handleMessage(msg Message) {
if isFromUser(msg) {
response := aiModule.Process(msg.Text)
sendMessage(response, msg.ChatID)
}
}
  • Архитектурные решения
    Создание масштабируемого промежуточного сервиса, который:

    • обрабатывает входящие сообщения асинхронно,
    • умеет работать в режиме высокой нагрузки,
    • обеспечивает устойчивость к сбоям сторонних API,
    • логирует взаимодействия для последующего аудита.
  • Организация очередей и конкурентность
    Для обеспечения масштабируемости и отказоустойчивости важно правильно организовать обработку сообщений, например, используя очереди (RabbitMQ, Kafka) и горутины:

func worker(queue <-chan Message) {
for msg := range queue {
process(msg)
}
}

func main() {
queue := make(chan Message, 100)
for i := 0; i < 10; i++ {
go worker(queue)
}
// получение и отправка в очередь
}
  • Тестирование и мониторинг
    Важно обеспечить качественное покрытие тестами (юнит, интеграционные), мониторинг задержек, ошибок интеграции и качества ответов ИИ.

Подобная задача требует навыков в проектировании распределённых систем, интеграции API, работе с асинхронными потоками, реализации безопасных соединений и внедрении ML/AI-технологий — что делает её крайне интересной и ценной с точки зрения роста компетенций.

Вопрос 7. Для чего необходимо транскодировать видео в различные форматы?

Таймкод: 00:17:12

Ответ собеседника: правильный. Чтобы видео можно было смотреть в разных разрешениях, скачивать для разных программ и обеспечивать совместимость с различными устройствами и форматами.

Правильный ответ:
Транскодирование видео — это процесс преобразования видеофайла из одного формата или кодека в другой. Оно имеет критическую важность по нескольким причинам:

  • Обеспечение совместимости
    Разные устройства (смартфоны, планшеты, телевизоры, ПК) и программы могут поддерживать разные форматы и кодеки. Например, один браузер может поддерживать H.264, а другой — VP9. Транскодирование позволяет сделать видео доступным для всех целевых платформ.

  • Адаптация к сетевым условиям и устройствам
    Для потоковой передачи важно иметь несколько версий видео в разных разрешениях и битрейтах (например, 240p, 480p, 720p, 1080p). Это позволяет использовать адаптивный стриминг (HLS, DASH), где плеер динамически выбирает качество в зависимости от скорости соединения пользователя, обеспечивая плавный просмотр.

  • Оптимизация размера и качества
    Использование современных кодеков (например, H.265/HEVC или AV1) позволяет снизить размер файла без потери качества по сравнению с устаревшими (например, MPEG-2 или H.264). Это важно для экономии трафика и ресурсов хранения.

  • Подготовка для редактирования и постобработки
    Некоторые форматы и кодеки лучше подходят для монтажа и обработки (например, ProRes), поэтому исходный материал часто перекодируют перед редактированием, а затем — в формат для доставки.

  • Требования по лицензированию и патентам
    Некоторые форматы (например, AV1) являются открытыми и не требуют лицензионных отчислений, что важно для масштабных платформ.

Практический пример:
Допустим, исходное видео — в 4K разрешении и кодеке HEVC. Для поддержки всех платформ его транскодируют в:

  • H.264 с разрешениями 1080p, 720p, 480p для совместимости с большинством браузеров.
  • VP9 для экономии трафика у Android-устройств.
  • AV1 для будущей поддержки и экономии на лицензиях.

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

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

Вопрос 8. Какие протоколы используются для потоковой передачи (стриминга) видео и что о них известно?

Таймкод: 00:21:04

Ответ собеседника: неполный. Упомянул, что для стриминга часто используют UDP, который передает данные пакетами, собираемыми на клиенте.

Правильный ответ:
Видеостриминг использует широкий спектр сетевых протоколов и технологий, каждый из которых решает свои задачи. Ниже — обзор основных решений:

1. Транспортные протоколы

  • UDP (User Datagram Protocol)
    Используется из-за низких задержек и меньших накладных расходов по сравнению с TCP. Однако, UDP не гарантирует доставку, порядок и отсутствие дублирования пакетов. Подходит для real-time стриминга, когда важна скорость, а не идеальное качество.

  • TCP (Transmission Control Protocol)
    Обеспечивает надежную доставку данных и контроль порядка пакетов, что важно для адаптивного стриминга и VoD (Video on Demand). Используется большинством современных решений, так как работает поверх HTTP и легко проходит через NAT и прокси.

2. Протоколы передачи мультимедиа

  • RTP (Real-time Transport Protocol)
    Построен поверх UDP, обеспечивает передачу аудио и видео с временными метками и номерами пакетов для синхронизации. Обычно используется в сочетании с RTCP (Real-time Control Protocol) для мониторинга качества.
    Часто применяется в IP-телефонии, видеоконференциях (WebRTC).

  • RTSP (Real Time Streaming Protocol)
    Управляющий протокол для медиа-сессий (play, pause, teardown). Передача данных идет по RTP. Используется для IP-камер, медиасерверов.

  • RTMP (Real Time Messaging Protocol)
    Разработан Adobe для Flash. Передача по TCP. До сих пор используется для ingest (передачи потока от источника к серверу, например, OBS → YouTube), но проигрывание во Flash устарело.

  • HLS (HTTP Live Streaming)
    Технология Apple. Основана на делении видео на маленькие сегменты (обычно по 2-10 секунд), которые передаются по HTTP.
    Поддерживает адаптивное качество. Использует только TCP. Декларируется как стандарт для iOS-устройств.

  • MPEG-DASH (Dynamic Adaptive Streaming over HTTP)
    Аналог HLS, разработанный MPEG. Поддерживает адаптивный стриминг по HTTP. Более гибкий и стандартизированный. Работает поверх TCP.

  • WebRTC
    Технология для real-time коммуникаций, использует UDP + DTLS + SRTP. Обеспечивает низкие задержки, активно применяется в видеозвонках и интерактивных сервисах.

3. Почему популярны HTTP-базированные протоколы (HLS, DASH)

  • Совместимы с существующей инфраструктурой (CDN, кэш, балансировщики).
  • Легко проходят через NAT, прокси, файерволы.
  • Позволяют использовать адаптивный bitrate.
  • Используют надежный TCP, что уменьшает количество артефактов и потерь.

Итог:

  • Для живых трансляций с минимальной задержкой — RTP/RTSP, RTMP или WebRTC.
  • Для массового вещания и VoD — HLS и DASH.
  • Для ingest (передачи от стримера к серверу) — RTMP.
  • Для конечных пользователей — чаще HLS/DASH по HTTP поверх TCP.

Понимание особенностей этих протоколов позволяет выбирать оптимальные решения для конкретных задач — от видеозвонков до вещания на миллионы зрителей.

Вопрос 9. Какие функции должен выполнять сервис для оптимизации видео?

Таймкод: 00:26:20

Ответ собеседника: правильный. Принимает сырое видео, меняет разрешение, битрейт и формат, создаёт оптимизированные версии и кладёт их в хранилище.

Правильный ответ:
Сервис оптимизации видео (иногда называют Video Transcoding Service или Video Processing Pipeline) — это ключевой компонент видеоплатформ, обеспечивающий подготовку видео для эффективного хранения, передачи и воспроизведения. Его задачи включают:

  • Прием исходного контента
    Получение видео от пользователя, через API, загрузку из хранилища или ingest-канал. Возможно, с предварительной валидацией формата и метаданных.

  • Транскодирование и перекодировка
    Создание нескольких копий видео с разным:

    • Разрешением (например, 2160p, 1080p, 720p, 480p, 360p) для поддержки различных устройств и скоростей соединения.
    • Битрейтом — для балансировки качества и трафика.
    • Кодеками (H.264, H.265/HEVC, VP9, AV1) для совместимости и экономии ресурсов.
    • Форматами контейнеров (MP4, WebM, MKV) в зависимости от платформ.

    Используются инструменты как ffmpeg или специализированные библиотеки.
    Пример команды ffmpeg:

    ffmpeg -i input.mp4 -c:v libx264 -b:v 1500k -s 1280x720 -c:a aac output_720p.mp4
  • Построение адаптивных потоков
    Для HLS или MPEG-DASH сегментирует видео на маленькие части (обычно 2-10 секунд) и создает плейлисты, которые позволяют плееру выбирать качество в реальном времени.

  • Оптимизация сжатия и качества
    Использование настроек кодека (профилей, CRF, GOP, B-frames), чтобы добиться лучшего соотношения размера и визуального качества.

  • Извлечение и обработка метаданных
    Получение информации о длительности, битрейте, кодеках, создание превью, скриншотов, генерация таймлайнов.

  • Обработка аудио
    Транскодирование аудиодорожек, нормализация громкости, удаление лишних каналов или шумоподавление.

  • Сохранение оптимизированных версий
    Загрузка результатов в объектное хранилище (например, S3, MinIO), кеш CDN или другую инфраструктуру доставки.

  • Интеграция с системами CDN и delivery
    Обеспечение быстрых и надежных путей доставки пользователям.

  • Мониторинг и логирование
    Отслеживание статусов задач, ошибок, времени обработки, качества.

  • Параллельная и масштабируемая обработка
    Использование очередей (Kafka, RabbitMQ, SQS) и worker-пулов для масштабирования по нагрузке, чтобы обрабатывать сотни и тысячи видео одновременно.

В некоторых случаях сервис может также заниматься:

  • Распознаванием лиц или объектов,
  • Автоматическим созданием субтитров,
  • Детектированием нежелательного контента,
  • Водяными знаками и DRM-защитой.

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

Вопрос 10. Какие видеокодеки вам известны и какой лучше выбрать для видеосистемы?

Таймкод: 00:29:27

Ответ собеседника: неполный. Упомянул, что знает о существовании разных кодеков, но конкретно не помнит, после подсказки согласился, что можно выбрать H.265.

Правильный ответ:
Современные видеокодеки — это стандарты сжатия, обеспечивающие баланс между качеством изображения, размером файла и вычислительными затратами. Выбор кодека зависит от целей, аудитории и инфраструктуры.

Основные видеокодеки:

  • MPEG-2
    Старый стандарт, используется в DVD и цифровом телевидении. Обеспечивает низкое сжатие, устарел для новых систем.

  • H.264 (AVC, Advanced Video Coding)
    Самый распространённый кодек. Высокое качество при умеренном размере файлов. Поддерживается почти всеми устройствами и браузерами. Универсальный выбор для совместимости.

  • H.265 (HEVC, High Efficiency Video Coding)
    Новый стандарт, обеспечивает ~50% меньший битрейт при аналогичном качестве по сравнению с H.264. Поддержка расширяется, но есть вопросы по лицензированию. Хорош для 4K, 8K и стриминга, где важна экономия трафика.

  • VP8 и VP9
    Разработаны Google, открытые и бесплатные. VP9 обеспечивает эффективность, схожую с HEVC, без лицензий. Хорошо поддерживается в YouTube и браузерах на Chromium. Ограниченная поддержка в аппаратных декодерах.

  • AV1
    Новый открытый и бесплатный кодек от консорциума AOMedia. Предлагает лучшее сжатие, чем VP9 и HEVC (~30% экономии). Активно развивается, уже поддерживается в Chrome, Firefox, Edge. Аппаратная поддержка пока ограничена, но растет.

  • ProRes, DNxHD
    Используются для профессионального монтажа, с низким сжатием и высокой качественной потерей. Для систем доставки видео не подходят.


Как выбрать кодек для вашей системы:

  1. Совместимость

    • Для массового VoD и стриминга — базово H.264, так как его поддерживают все устройства.
    • Для новых систем с упором на экономию трафика и высокое качество — H.265 или VP9.
    • Для будущего или если важна бесплатность — AV1.
  2. Лицензирование

    • H.264 и HEVC требуют лицензионных отчислений за некоторые применения.
    • VP8, VP9 и AV1 — открытые и бесплатные.
  3. Аппаратное ускорение

    • Важно для мобильных и embedded-устройств.
    • H.264 поддерживается повсеместно.
    • HEVC — активно внедряется.
    • VP9 и AV1 — поддержка только в новых чипах.
  4. Цели системы:

    • Для live-стриминга в хорошем качестве — HEVC или VP9.
    • Для быстрой совместимости — H.264.
    • Для долгосрочного VoD с минимальными затратами на трафик — AV1, когда поддержка станет шире.

Резюме:
В большинстве случаев разумно использовать несколько кодеков параллельно:

  • Основной — H.264 для максимальной совместимости.
  • Более эффективный — H.265 или VP9 для устройств и клиентов, где они поддерживаются.
  • Перспективный — AV1 для экономии в будущем.

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

Вопрос 11. Какой тип базы данных — реляционную или NoSQL — лучше выбрать для хранения информации о видео в такой системе?

Таймкод: 00:33:03

Ответ собеседника: правильный. Сначала выбрал реляционную базу из-за привычки, но после обсуждения масштабируемости согласился, что лучше использовать NoSQL, например MongoDB.

Правильный ответ:
Выбор между реляционной и NoSQL базой данных зависит от требований к масштабируемости, гибкости схемы данных, надежности и типов запросов. Рассмотрим это более подробно.


1. Особенности хранения данных о видео:

  • Метаданные видео: название, автор, длительность, разрешения, форматы, статус обработки.
  • Связанные данные: комментарии, лайки, теги, категории.
  • Потенциально огромные объемы данных (миллионы видео).
  • Высокая скорость записи (загрузки) и чтения (просмотры, рекомендации).
  • Возможные изменения схемы с течением времени (новые атрибуты).

2. Реляционные базы данных (PostgreSQL, MySQL)

  • Плюсы:
    • Сложные запросы (JOIN, агрегаты).
    • ACID-транзакции, строгая целостность данных.
    • Проверенная технология.
  • Минусы:
    • Масштабирование — в основном вертикальное, что ограничивает рост.
    • Менее гибкие к изменениям схемы.
    • Могут становиться узким местом при огромных объемах данных.
  • Применение:
    • Для хранения критически важных данных, управления пользователями, платежами, транзакциями.
    • Для связанной, хорошо структурированной информации.

3. NoSQL базы данных (MongoDB, Cassandra, DynamoDB)

  • Плюсы:
    • Легко масштабируются горизонтально (шардинг).
    • Гибкая схема (добавление новых полей без миграций).
    • Хорошо подходят для хранения больших объемов полу-структурированных данных.
    • Высокая производительность при большом количестве чтений/записей.
  • Минусы:
    • Ограниченные возможности сложных запросов (хотя в MongoDB они расширяются).
    • Более слабые гарантии целостности (хотя есть механизмы транзакций).
  • Применение:
    • Хранение метаданных видео, логов, аналитики, больших потоков событий.
    • Динамически меняющаяся структура данных.

4. Комбинированный подход (Polyglot Persistence)
На практике часто используют обе технологии:

  • Реляционную БД для хранения данных о пользователях, платежах, связях.
  • NoSQL для метаданных видео, логов, статистики просмотров, рекомендаций.
  • Связь между ними можно строить по ID.

5. Почему NoSQL (например, MongoDB) лучше для метаданных видео:

  • Видео-метаданные часто полу-структурированные и могут меняться.
  • Требуется горизонтальное масштабирование по мере роста числа видео.
  • Высокая скорость записи и чтения.
  • Возможность легко добавлять новые атрибуты (например, теги, рекомендации, новые форматы).
  • Поддержка репликации и отказоустойчивости.

Пример хранения документа о видео в MongoDB:

{
"_id": "video123",
"title": "Как выбрать кодек",
"authorId": "user567",
"duration": 3600,
"resolutions": ["2160p", "1080p", "720p"],
"formats": ["h264", "hevc", "vp9"],
"status": "ready",
"uploadDate": "2023-10-01T12:00:00Z",
"tags": ["трансляция", "кодеки", "обработка"],
"views": 5234
}

Вывод:
Для масштабируемого хранения метаданных видео лучше подходит NoSQL база данных, например MongoDB или Cassandra, за счет гибкости схемы, высокой производительности и возможности масштабирования. Для связанных бизнес-данных можно дополнительно использовать реляционные базы. Такой гибридный подход обеспечивает баланс между гибкостью, масштабируемостью и надежностью.

Вопрос 12. Как оптимально реализовать авторизацию пользователей и почему выбран именно этот способ?

Таймкод: 00:41:17

Ответ собеседника: правильный. Выбран OAuth2 с access и refresh токенами, потому что это безопасно, удобно, просто реализовать, токены имеют срок жизни, а украденный access токен быстро протухает, что снижает риски.

Правильный ответ:
Для современных сервисов наиболее подходящим способом реализации авторизации является использование протокола OAuth 2.0 в связке с JWT (JSON Web Tokens), который обеспечивает масштабируемую, безопасную и удобную архитектуру.


Преимущества использования OAuth2 с access и refresh токенами:

  • Разделение процессов аутентификации и авторизации
    OAuth2 позволяет делегировать аутентификацию стороннему провайдеру (Google, Facebook, собственный Identity Server), а не держать пароли у себя, что повышает безопасность.

  • Access token
    — это короткоживущий (например, 5–15 минут) токен, подписанный сервером, который клиент использует для доступа к API.
    Он содержит всю необходимую информацию (например, user id, роль) и легко валидируется на сервере без обращения к базе.
    Если access token украден, ущерб ограничен временем его жизни.

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

  • Безопасность

    • Использование HTTPS обязательно для защиты токенов.
    • Токены можно подписывать и шифровать.
    • Refresh токены можно отозвать, обеспечивая контроль над сессиями.
    • Возможность настройки гранулярных прав доступа (scopes).
  • Масштабируемость

    • Токен содержит всю необходимую информацию, API могут валидировать их автономно (без обращения к базе).
    • Упрощается горизонтальное масштабирование сервисов.
  • Удобство для клиентов

    • Нет необходимости постоянно хранить или передавать пароль.
    • Обеспечивается плавный user experience без постоянных переавторизаций.

Архитектура:

  1. Логин
    Пользователь вводит логин/пароль (или использует сторонний OAuth-провайдер).
  2. Получение токенов
    Сервер выдает пару access и refresh токенов.
  3. Доступ к API
    Клиент использует access token в заголовках:
    Authorization: Bearer <access_token>
  4. Обновление access token
    Когда access token истекает, клиент использует refresh token для запроса новой пары токенов.
  5. Выход
    Refresh token аннулируется, access token истекает, пользователь выходит.

Пример генерации и валидации JWT на Go:

import (
"github.com/golang-jwt/jwt/v5"
"time"
)

// Генерация
func GenerateAccessToken(userID string, secret []byte) (string, error) {
claims := jwt.MapClaims{
"sub": userID,
"exp": time.Now().Add(15 * time.Minute).Unix(),
"role": "user",
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString(secret)
}

// Валидация
func ValidateToken(tokenString string, secret []byte) (*jwt.Token, error) {
return jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return secret, nil
})
}

Почему этот подход лучше:

  • Соответствует лучшим мировым практикам.
  • Повышает безопасность за счет короткоживущих access токенов и управляемых refresh токенов.
  • Обеспечивает масштабируемую архитектуру без необходимости постоянных запросов к базе.
  • Гибко интегрируется с SSO, сторонними провайдерами, мобильными и веб-клиентами.
  • Упрощает управление сессиями и отзывом доступа.

Резюме:
Использование OAuth2 с access и refresh токенами — оптимальный, безопасный и масштабируемый способ реализации авторизации, который защищает от большинства рисков, обеспечивает удобство для пользователей и гибкость для системы.

Вопрос 13. Как пользователь получает доступ к своему профилю через систему авторизации?

Таймкод: 00:54:34

Ответ собеседника: правильный. Пользователь получает пару токенов через SSO, затем с этим токеном обращается к сервису профилей, где подпись токена проверяется и возвращаются данные пользователя.

Правильный ответ:
Доступ пользователя к своему профилю в системе, использующей авторизацию на базе OAuth2 и SSO (Single Sign-On), реализуется по следующему сценарию:


1. Аутентификация и получение токенов

  • Пользователь проходит аутентификацию через SSO-провайдера (например, корпоративный Identity Server, Google, Keycloak).
  • В ответ получает пару токенов:
    • Access token (короткоживущий, с информацией о пользователе и правах).
    • Refresh token (для обновления access token без повторного входа).

2. Обращение к API профиля

  • Клиент (мобильное приложение, браузер, сервис) формирует HTTP-запрос к сервису профилей:
    GET /api/profile
    Authorization: Bearer <access_token>
  • Access token отправляется в заголовке Authorization.

3. Валидация токена на стороне сервиса профилей

  • Сервис профилей проверяет подпись access token (например, JWT), используя публичный ключ Identity провайдера.
  • Проверяет срок действия токена (exp).
  • Проверяет права доступа (scopes, роли).
  • Если токен валиден — извлекает из него идентификатор пользователя (sub) и другие нужные атрибуты.

4. Получение данных профиля

  • Используя user ID из токена, сервис профилей запрашивает данные из своей базы (или кеша).
  • Например, email, имя, настройки, роль, список прав.
  • Формирует и возвращает JSON-ответ клиенту.

5. Обработка ошибок

  • Если токен истек или подпись невалидна — возвращается 401 Unauthorized.
  • Клиент может использовать refresh token для обновления access token и повторить запрос.

Преимущества такого подхода:

  • Безопасность:
    Токен подписан, нельзя подделать. Нет передачи пароля.
  • Масштабируемость:
    Валидация токена происходит локально, без запросов к Identity серверу.
  • Быстродействие:
    Меньше задержек при проверке.
  • Удобство:
    Пользователь может использовать один логин (SSO) для всех сервисов.
  • Гибкость:
    Можно легко управлять правами доступа, временем жизни токенов, отзывом refresh токенов.

Пример валидации JWT токена на Go:

func GetProfile(w http.ResponseWriter, r *http.Request) {
tokenStr := extractBearerToken(r.Header.Get("Authorization"))
token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
return publicKey, nil // публичный ключ для проверки подписи
})
if err != nil || !token.Valid {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
claims := token.Claims.(jwt.MapClaims)
userID := claims["sub"].(string)

profile := loadProfileFromDB(userID)
json.NewEncoder(w).Encode(profile)
}

Резюме:
Пользователь, получив access token через SSO, использует его для безопасного доступа к своему профилю. Сервис профилей валидирует токен, извлекает из него user ID и возвращает актуальные данные. Такой подход обеспечивает высокую безопасность, масштабируемость и удобство интеграции различных сервисов внутри экосистемы.

Вопрос 14. Как пользователь получает свой профиль, используя access token?

Таймкод: 00:54:34

Ответ собеседника: правильный. Пользователь авторизуется и получает access token, потом обращается с ним к сервису профилей, где подпись токена проверяется и возвращаются данные профиля.

Правильный ответ:
Когда пользователь уже прошел аутентификацию и получил access token (например, через OAuth2), дальнейшее получение профиля происходит в следующем порядке:


1. Формирование запроса к сервису профилей
Пользовательский клиент (веб, мобильный или другой сервис) добавляет access token в заголовок HTTP-запроса:

GET /api/profile
Authorization: Bearer <access_token>

2. Прием запроса сервисом профилей
Сервис извлекает и валидирует access token:

  • Проверяет подпись JWT (используя публичный ключ или секрет).
  • Проверяет срок действия (exp).
  • Проверяет, что токен не отозван и обладает нужными правами (scopes, роли).

3. Извлечение данных из токена

  • Если access token — JWT, из него извлекается, например, sub (идентификатор пользователя).
  • Пример claims токена:
{
"sub": "user123",
"email": "user@example.com",
"role": "user",
"exp": 1712345678
}

4. Получение профиля пользователя

  • По sub сервис ищет профиль в базе данных, кешах или сторонних сервисах.
  • Собирает и возвращает профиль: имя, аватар, email, настройки и т.п.
  • Ответ:
{
"id": "user123",
"name": "Иван Иванов",
"email": "user@example.com",
"avatar": "https://cdn.example.com/avatars/user123.png",
"preferences": { ... }
}

5. Ответ клиенту

  • Если токен валиден — профиль возвращается.
  • Если токен истек или недействителен — возвращается 401 Unauthorized.

Важные моменты:

  • Access token — это одноразовый ключ к API, который нельзя использовать после истечения срока.
  • Вся авторизация выполняется без хранения сессий на сервере (stateless).
  • Для безопасности все запросы должны идти по HTTPS.
  • Можно внедрить кеширование профиля для уменьшения нагрузки.

Пример на Go:

func ProfileHandler(w http.ResponseWriter, r *http.Request) {
tokenStr := extractBearerToken(r.Header.Get("Authorization"))
token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
return publicKey, nil
})
if err != nil || !token.Valid {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
claims := token.Claims.(jwt.MapClaims)
userID := claims["sub"].(string)

profile := fetchProfile(userID)
json.NewEncoder(w).Encode(profile)
}

Резюме:
Пользователь, имея access token, отправляет его вместе с запросом к API профиля. Сервис валидирует токен, извлекает идентификатор пользователя и возвращает его профиль. Такой подход обеспечивает безопасный, быстрый и масштабируемый доступ к данным пользователя без необходимости постоянной аутентификации.