Собеседование на Middle Go с лидом из Fivegen. Проектируем дизайн видеосервиса
Сегодня мы разберем подробное техническое собеседование, в ходе которого кандидат и интервьюер проектируют архитектуру высоконагруженной видеоплатформы, аналогичной 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
Используются для профессионального монтажа, с низким сжатием и высокой качественной потерей. Для систем доставки видео не подходят.
Как выбрать кодек для вашей системы:
-
Совместимость
- Для массового VoD и стриминга — базово H.264, так как его поддерживают все устройства.
- Для новых систем с упором на экономию трафика и высокое качество — H.265 или VP9.
- Для будущего или если важна бесплатность — AV1.
-
Лицензирование
- H.264 и HEVC требуют лицензионных отчислений за некоторые применения.
- VP8, VP9 и AV1 — открытые и бесплатные.
-
Аппаратное ускорение
- Важно для мобильных и embedded-устройств.
- H.264 поддерживается повсеместно.
- HEVC — активно внедряется.
- VP9 и AV1 — поддержка только в новых чипах.
-
Цели системы:
- Для 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 без постоянных переавторизаций.
Архитектура:
- Логин
Пользователь вводит логин/пароль (или использует сторонний OAuth-провайдер). - Получение токенов
Сервер выдает пару access и refresh токенов. - Доступ к API
Клиент использует access token в заголовках:Authorization: Bearer <access_token>
- Обновление access token
Когда access token истекает, клиент использует refresh token для запроса новой пары токенов. - Выход
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 профиля. Сервис валидирует токен, извлекает идентификатор пользователя и возвращает его профиль. Такой подход обеспечивает безопасный, быстрый и масштабируемый доступ к данным пользователя без необходимости постоянной аутентификации.