Twitch — видеостриминговый сервис, специализирующийся на тематике компьютерных игр, в том числе трансляциях геймплея и киберспортивных турниров.
- Регистрация аккаунтов пользователей (авторов трансляций и зрителей)
- Просмотр прямых трансляций пользователей
- Поиск и подбор идущих трансляций
- Чат трансляции
- Система подписок на каналы
- Подсчет количества зрителей, подписок
Целевая аудитория (статистика)
По состоянию на январь 2023 года twitch ежемесячно посещают 140 миллионов уникальных пользователей.
Twitch имеет 31 миллион активных пользователей в день (DAU).
Распределение трафика по странам в процентах:
-
США - 20.46%
-
Германия - 6.07%
-
Корея - 5.32%
-
Россия - 4.56%
-
Франция - 4.27%
- Месячная аудитория - 140 млн
- Дневная аудитория - 31 млн
- Средний размер хранилища пользователя - отсутствует, так как хранение записей не предусмотрено
- Cреднее количество одновременно активных трансляции - 107тыс (по данным на 2022 год)
Допустим, что в среднем в секунду отправляется 700 сообщений на основе статистики, тогда в день 60млн
Тип запроса | Среднее количество(млн/день) |
---|---|
Авторизация | 2 |
Список подписок | 2 |
Поиск/подбор | 7 |
Отправка сообщения в чат | 60 |
Начало трансляции | 1 |
Cтраница стримера | 7 |
Просмотр стримов: одновременно смотрит стримы около 2.5млн человек [2].
Потоковая передача видео: ежедневно загружается 2млн часов стримов [3].
Возьмем средний битрейт для качества 720p - 3000кбит/с
2 000 000 * 60 * 60 = 72 000 000 000 cекунд стримов в день
72 000 000 000сек * 3000кбит/с = 2.16 * 10^13 кбит = 2 574 920Гб/cутки ~ 2 600 000 Гб/сутки
# Пусть 80% от суточного трафика сконцетрировано на вечер 17-21 тогда пиковое потребление:
2 600 000 * 8 * 0.8 / (4 * 3600) = 1155 Гбит/с
Страница стримера: шапка, аватар, инофрмация, банеры и тд. Оценим в 2000Кбайт
Тип запроса | Объем одного запроса в Кб | Суточный объём (Гб/сутки) | Пиковое потребление в течении суток (Гбит/с) |
---|---|---|---|
Авторизация | 1 | 2 | 0.0008 |
Отправка сообщения в чат | 0.25 | 15 | 0.01 |
Загрузка трансляции | - | 2 600 000 | 1155 |
Ежедневно просматривается 61млн часов стримов [4]
61 000 000 * 60 * 60 = 219 600 000 000 cекунд стримов в день
219 600 000 000сек * 3000кбит/с = 6.588 * 10^14 ~ 78 500 000 Гб/сутки
В среднем в день запущено 107тыс стримов, а стримы смотрит 2.5 млн человек, пусть основная часть зрителей смотрит только четверть всех стримов, тогда среднее количество людей, пишуших в чат - 2 500 000 / (107 000 / 4) ~ 100. Значит суточный объем входящего трафика, влечет 100 кратный объем исходящего, т,к пользователь будет читать чат с 100 другими людьми.
15 * 100 = 1500 Гб
Пусть 80% от суточного трафика приходятся на вечер с 17 до 21, тогда трафик в пиковые часы:
7 * 8 * 0.8 / (4 * 3600) = 0.003 Гбит/с - страница стримера
78 500 000 * 8 * 0.8 / (4 * 3600) = 35 000 Гбит/c - просмотр стрима
1500 * 8 * 0.8 / (4 * 3600) = 0.6 Гбит/c - сообщения
Тип запроса | Объем одного запроса в Кб | Суточный объём (Гб/сутки) | Пиковое потребление в течении суток (Гбит/с) |
---|---|---|---|
Отправка сообщения в чат | 0.25 | 1500 | 0.6 |
Просмотр трансляции | - | 78 500 000 | 35 000 |
Страница стримера | 2000 | 7 | 0.003 |
Авторизация:
2 000 000 авторизаций в день / 24 / 3600 ~ 25 RPS
Поиск/подбор:
7 000 000 / 24 / 3600 ~ 81 RPS
Отправка сообщений:
60 000 000 / 24 / 3600 ~ 700 RPS
Начало просмотра стрима:
Т.к поиск и подбор составляет в среднем 7 млн запросов в день, пусть 95% всех поисков/подборов успешны и пользователь все таки решается зайти на стрим, тогда:
7 000 000 * 0.95 / 24 / 3600 = 76 RPS
Страница стримера:
7 000 000 / 24 / 3600 = 80
Тип запроса | RPS |
---|---|
Авторизация | 25 |
Список подписок | 25 |
Поиск/подбор | 81 |
Отправка сообщения в чат | 700 |
Начало просмотра стрима | 76 |
Cтраница стримера | 80 |
В качестве СУБД будем использовать PostgreSQL. Из того, что сервис подразумевает большее число чтений, нежели записи, будем использовать master/slave репликацию.
4*64 + 2048 + 4 + 8 = 2316 байт на одного пользователя
140 000 000 * 2316 = 3.2424 * 10^11 байт = = 0.294 Терабайт
4 + 4 + 4 = 12 байт на одну подписку
Допустим в среднем, один человек имеет 15 подписок, тогда
140 000 000 * 15 * 12 = 25200000000 байт = 0,022 Терабайт
Так как в MVP нет записи стримов, после окончания информация о стриме удаляется. Учитыва 107тыс активных трансляций:
4 + 4 + 4 + 64 + 8 = 84 байт на один стрим
107 000 * 84 = 8 988 000 байт = 8.5 Мегабайт
Хранить чат каждого стрима является дорогостоющей операцией, т.к это огромная нагрузка на базу в виде большого числа операций записи, поэтому хранить историю сообщений нет необходимости, к тому же запись стрима не храниться.
Сообщения в чате будут реализованы через WS, следовательно 0 байт данных.
[0.294 Терабайт + 0.022 Терабайт + 0.000008 Терабайт] ~ 0.32 Терабайта данных
Редис будет использоваться для хранения сессий пользователя и счетчика зрителей на стриме.
Пусть ровно половина всех пользователей хоть раз заходит и обновляет куку
70 000 000 * (4 + 32) = 2 520 000 000 байт = 0.002 Терабайта
107 000 * (4 + 4) = 856 000 байт ~ 1 Мб
Технология | Применение | Причина выбора |
---|---|---|
PostgreSQL | База данных | Простота использования, совместимость с Golang, сравнительно легкая расширяемость |
TypeScript | Язык используемый для написание фронтенда. Поддержка HLS для стримов в браузере | Типизация, ошибки при компиляции |
React | Фреймворк для написания клиентской части. | Скорость написания, реактивность интерфейса, высокая популярность |
Nginx | Веб-сервер для отдачи статики, обратное прокси | Производительность, простота настройки |
Wowza streaming engine | Преобразование RTMP потока стримера в HLS потоки разного качества и различного FPS | Удобство настройки, скорость работы, совместимость с OBS(популярная программа у стримеров для захвата экрана) |
Nginx RTMP | модуль потоковой передачи медиа данных | Надежность, произовдительность |
Golang | Язык backend | Скорость написания, скорость работы, простота поддержки, популярность |
RedisDB | База данных | Высокая скорость из-за нахождения данных в оперативной памяти. Простота использования, совместимость с Golang |
Для балансировки применяется DNS балансировка, затем L7-балансировка на NGINX.
Сервис делится на несколько микросервисов
Сервис стримов - сервис для работы с данными о стримах, здесь добавляются и раздаются Stream-keys и ссылки на HLS потоки, также осуществляется работа с подборками активных стримов
Сервис зрителей - учитывая расчеты, самый нагруженный по RPS сервис, подлежащий масштабированию при необходимости. Разместить подсчет количества зрителей на стриме и чаты рядом крайне удобно, так как каждый участник чата стрима в свою очередь является и зрителем.
Сервис авторизации и пользователей - сервис обрабатывающий запросы на авторизацию и работающий с данными пользователя.
Препологается, что все микросервисы будут написаны на GO и будут при необходимости общаться между собой по gRPC, что обеспечивает высокую скорость обмена данными между внутренними API сервиса.
Записи, как уже отмечалось ранее, происходят намного реже,чем чтение, соответсвенно следует использовать реплики на чтение данных из PostgreSQL. Следует использовать синхронную репликацию, при которой данные записываются сначала в WAL как минимум одной реплики, после чего исполняются в мастере. При такой схеме необходимо минимум 2 реплики БД, однако вероятность потери данных минимизируется и скорость чтения увеличивается.
JS-клиент и статические файлы раздаются NGINX, который также проксирует запросы на сами микросервисы.
При создании стрима на сайте, стример получает ссылку со Stream-KEY для последующего ведения трансляции через OBS Studio или его аналоги, отправляющие RTMP поток на Ingest-сервер, который проверяет ключ стрима и перенаправляет его RTMP-поток в существующий Nginx Load Balancer, который в свою очередь распределяет их между серверами транскодерами wowza. Сгенерированные уже HLS-потоки отправляются на краевой (Edge) сервер, далее по цепочке Edge сервера при необходимости забирают и ретранслируют поток ближе к зрителю.
Допустим у нас есть стрим из США, который хотят смотреть пользователи из России, в таком случае Российский edge сервер однократно будет забирать поток и ретранслировать его русским зрителям и все русские зрители будут обращаться к нему, что ускорит загрузку контента и уменьшит нагрузку на другой edge-сервер.
Зритель в свою очередь изначально обращается к балансировщику, который по IP-адресу может приблизительно понять его местоположение и направить на оптимальный краевой сервер.
Как вычислялось ранее - выходящего трафика на просмотр стримов - 35 000гбит в случае пиковой нагрузки. При использовании 40гбит-ных сетевых карт потребуется около.
35000/40 = 875
Зная, что максимально активными одновременно может быть 107 000 стримов, задачей edge сервера является хранение последних 10 секунд стрима для последующей передачи стрима в 6 разных качествах со средним битрейтом 3000 кбит/с
3000 * 6 = 18 мб
18 * 10 = 180 мб
180 * 107 000 = 18,3 тб
18,3 / 875 = 21 гб ОЗУ
Таким образом каждый edge сервер должен обладать минимум 21 гб ОЗУ, зная стандарты размеров оперативной памяти удобно использовать 4 x 6 = 24 гб озу.
Объем диска в edge серверах не имеет особого значения, можно использовать SSD на 50 гбайт.
875 edge серверов
Западаное побережье США - 15% edge-серверов (131) Восточное побережье США - 15% edge-серверов (131) Германия (Frankfurt) - 10% edge-серверов (87) Корея - 10% edge-серверов (87) Бразилия - 10% edge-серверов (87) Россия - 10% edge-серверов (87) ЮАР - 5% edge-серверов (44) Канада - 5% edge-серверов (43) Франция - 5% edge-серверов (43) Англия - 5% edge-серверов (43) Турция - 5% edge-серверов (43) Испания - 5% edge-серверов (43) Австралия - 5% edge-серверов (43)
CPU | RAM (Гб) | Тип диска | Объем диска (Гб) | Пропускная способность (Гб/с) |
---|---|---|---|---|
8 | 24 | SSD | 50 | 40 |
Входящего трафика в пиковой нагрузке 1115Гбит/c. При использовании тех же сетевых карт
1115 / 40 = 28 # ingest
1115 / 20 = 56 # wowza-транскодер
На Ingest сервер приходит один поток максимально высокого качества RTMP стрима.
CPU | RAM (Гб) | Тип диска | Объем диска (Гб) | Пропускная способность (Гб/с) |
---|---|---|---|---|
4 | 12 | SSD | 50 | 40 |
CPU | RAM (Гб) | Тип диска | Объем диска (Гб) | Пропускная способность (Гб/с) |
---|---|---|---|---|
16 | 64 | SSD | 128 | 20 |
CPU | RAM (Гб) | Тип диска | Объем диска (Гб) | Пропускная способность (Гб/с) |
---|---|---|---|---|
16 | 32 | SSD | 120 | 20 |
CPU | RAM (Гб) | Тип диска | Объем диска (Гб) | Пропускная способность (Гб/с) |
---|---|---|---|---|
64 | 24 | SSD | 50 | 20 |
CPU | RAM (Гб) | Тип диска | Объем диска (Гб) | Пропускная способность (Гб/с) |
---|---|---|---|---|
16 | 12 | SSD+HDD | 120+1000 | 20 |
Таким образом разделим все сервера по 10 регионам датацентрам (для каждых 5% edge-серверов)
- Западаное побережье США - 3 датацентра
- Восточное побережье США - 3 датацентра
- Германия - 2 датацентра
- Корея - 2 датацентра
- Бразилия - 2 датацентра
- Россия - 2 датацентра
- ЮАР - 1 датацентр
- Канада - 1 датацентр
- Франция - 1 датацентр
- Англия - 1 датацентр
- Турция - 1 датацентр
- Испания - 1 датацентр
- Австралия - 1 датацентр
Тогда в одном датацентре
Количество серверов на датацентр
Тип | Количество основных | Количество всего |
---|---|---|
Nginx | 13 | 260 |
Backend | 6 | 120 |
Database | 12 | 240 |
Ingest | 10 | 28 |
Edge | 40 | 875 |
Wowza | 20 | 56 |
Edge сервера находятся в непосредственных городах отдельно от датацентра, максимально близко к потребителям контента