Опыт реализации Open Source OTT TV CDN решения из 2015 года
06 Feb 2022 - freefd - DmitryZaytsev
Share on:В основе CDN 1 лежит принцип географически более близкого расположения серверов с контентом к пользователю, что увеличивает скорость доставки контента и снижает нагрузку на первичный источник (Origin).
Внимание:
- Статья является преработанной внутренней документации in-house OTT 2 TV CDN решения из 2015 года от российского ISP 3 федерального масштаба для Live трафика OTT.
- На 2022 год решение уже притерпело изменения, которые глобально не сказались на основополагающих архитектурных аспектах.
- Статья не описывает состав и принцип работы OTT Middleware 4.
- Решение работает в пределах одной ASN 5.
- Реальное название бренда заменено на ACME 6.
Упрощённое объяснение разницы между классическим распространением контента с единичного сервера:
и через CDN:
Составляющие CDN для ACME
Функциональные
В иерархии CDN реализации для ACME можно выделить следующие функциональные составляющие:
Origin Streamer
Физически представляет собой сервер с большим количеством 7200 RPM 7 дисков для хранения и раздачи контента. Контент на стримеры доставляется по NFS 8 10G с Packager’ов 9 (EN). То есть на серверах находится prepackaged контент, уже разбитый на сегменты (chunks). Раздаёт media m3u8 10 манифест и контент для конечного пользователя.
Внимание:
На 2022 год это не самый лучший вариант стриминга. Например, можно использовать пакетированиее на лету с помощью NGINX-based VOD Packager 11 (EN)
CDN Precache
Выполняет две функции:
- Ограничивает трафик в сторону Origin Streamer’ов, защищая от перегрузки канала и превышения лицензионных ограничений.
- Обеспечивает отказоустойчивость и балансировку между Origin Streamer’ами. Представляет собой виртуальную машину или физический сервер с большим количеством RAM 12, куда кешируется контент в момент проксирования пользовательских запросов, и 10G+ Ethernet.
CDN Cache
Горизонтально масштабируемая единица комплекса, непосредственно раздающая контент пользователям. Представляет собой виртуальный или физический сервер с умеренным количеством RAM, куда кешируется контент в момент проксирования пользовательских запросов, и 1G или 10G+ Ethernet, в зависимости от технических возможностей сервера.
Router
Каналообразующая единица комплекса, принимающая анонсы BGP Anycast 13 от ближайших CDN Cache’ров, маршрутизирующая и балансирующая пользовательский трафик до них. Также организовывает отказоустойчивость решения, выбирая для пользовательского трафика новый путь до CDN Cache’ров в случае выхода из строя ближайших.
Программные
Вся программная реализация CDN использует Open Source продукты:
Операционная Система
В качестве платформы все серверы, за исключением Origin Streamers, используют CentOS 14 (EN) - дистрибутив Linux, основанный на коммерческом Red Hat Enterprise Linux компании Red Hat и совместимый с ним. Origin Streamer’ы используют Red Hat Enterprise Linux 15 (EN).
Внимание:
В результате принятых Red Hat решений, c 2021 года CentOS 8 трансформирован в CentOS Stream 16 (EN) и считается платформой для разработки изменений, включаемых затем в RHEL редакцию. Более не рекомендуется как промышленная полноценная замена RHEL.
Кеширующий HTTP-прокси сервер
Доставку OTT-контента и кеширование в процессе проксирования выполняет Nginx 17 - HTTP-сервер и обратный прокси-сервер, почтовый прокси-сервер, а также TCP/UDP прокси-сервер общего назначения. Серверы Nginx присутствуют на Origin Streamer’ах, CDN Precache’рах и CDN Cache’рах.
Демон динамической IPv4/IPv6 маршрутизации
Для задач динамической маршрутизации IPv4/IPv6 на платформе Linux в CDN для ACME используется The BIRD Internet Routing Daemon 18 (EN). С его помощью CDN Cache’ры анонсируют BGP Anycast IP.
Внимание:
В 2022 году, пожалуйста, используйте BIRD2 реализацию.
Система мониторинга daemon’ов
Monit 19 (EN) выполняет локальных мониторинг сервисов, позволяет выполнять действия при достижении определенных событий. Отслеживает работоспособность Nginx.
Система мониторинга
Zabbix 20 отслеживает статусы сервисов ОС серверов и ключевые метрики комплекса. Считает статистику по трафику для Live/VoD 21/PVR, Cache Hit Ratio 22 (EN), утилизацию кеша серверов, трафик из/в Origin.
Внимание:
В 2022 году имеет смысл рассмотреть альтернативы Zabbix, например, Prometheus 23 (EN).
Архитектурная схема CDN для ACME
Как видно на схеме, коммуникации Cache <-> Precache выполняются в формате Active-Active.
Диаграмма последовательности потоков трафика пользовательского устройства
Для доставки фрагментов видеопотока используется классическая схема для HLS/DASH с двумя m3u8 манифестами: master и media.
Подробней про HLS/DASH и ABR можно прочесть в What’s HTTP Live Streaming 24 (EN). Общую последовательность запросов можно представить как
Важно заметить, что master и media манифесты не всегда обязан предоставлять Origin, порой это может быть совершенно отдельный ресурс. В этом случае Origin от конечного пользователя полностью скрыт CDN.
Настройки программного обеспечения комплекса
Упрощённая сетевая схема примера подключения Cache сервера к Router
BGP: Juniper MX
Примеры настроек BGP 25- и BFD 26 (EN)-сессий для Juniper MX 27 в классическом show configuration
формате:
protocols {
...
bgp {
...
group tv-cdn {
type external;
description "-- OTT TV CDN Servers --";
mtu-discovery;
log-updown;
import import-tv-cdn;
family inet {
unicast {
prefix-limit {
maximum 5;
teardown idle-timeout 5;
}
}
}
export export-default;
multipath;
neighbor 198.51.100.178 {
description "-- msk-cache-01.tv.acme.tld";
peer-as 64511;
bfd-liveness-detection {
minimum-interval 250;
}
}
...
}
...
}
}
policy-options {
prefix-list default {
0.0.0.0/0;
}
policy-statement export-default {
term default-route {
from {
prefix-list default;
}
then accept;
}
then reject;
}
policy-statement import-tv-cdn {
term reject-default-route {
from {
route-filter 0.0.0.0/0 exact;
}
then reject;
}
term reject-multicast {
from {
route-filter 224.0.0.0/4 orlonger;
}
then reject;
}
term bgp {
from protocol bgp;
then {
community set type-aggregatable-customer;
community add acme-msk;
accept;
}
}
}
}
Опция BGP Multipath 28 (EN) используется для отказоустойчивости и балансировки пользовательского трафика между несколькими серверами в локации. BFD-сессия настроена для более быстрого разрыва BGP-сессии и перестройки таблицы маршрутов в случае недоступности Cache сервера.
BGP: CDN Cache
Пример настроек BIRD для CDN Cache’ров:
protocol device {
scan time 10;
}
protocol direct {
interface "lo*";
}
protocol bgp msk_cache_01_tv_pop01_public_bgp {
description "-- msk-r1-pop01.acme.tld irb.1010";
router id 198.51.100.178;
local as 64511;
neighbor 198.51.100.177 as 64496;
export where source = RTS_DEVICE;
import all;
source address 198.51.100.178;
next hop self;
}
protocol bfd msk_r1_pop01_bfd {
interface "eth0" {
interval 250 ms;
multiplier 3;
};
neighbor 198.51.100.177;
}
log syslog { debug, trace, info, remote, warning, error, auth, fatal, bug };
BIRD каждые 10 секунд будет перечитывать список интерфейсов и выбирать из них лишь lo
интерфейсы, на которых как secondary добавлен Anycast IP адрес 198.51.100.190. Анонсируются в BGP лишь Directly Connected интерфейсы (RTS_DEVICE
), которыми и являются lo
. Импортируются в виртуальную таблицу BGP любые префиксы от пира.
BFD работает на интерфейсе eth0
, настройки interval
и multiplier
идентичны настройкам Juniper MX.
ОС: CDN Cache, CDN Precache
Как известно, на подключениях 1G используется кодирование 8b/10b 29 (EN), то есть, на 10 байт переданной информации приходится 8 байт данных. Накладные расходы в объёмах переданного трафика в единицу времени для 1G интерфейса могут достигать 20%. Более предпочтительно использовать 10G+ интерфейсы, в которых используется уже 64b/66b 30 (EN) кодирование и накладные расходы не превышают 3-4%.
В зависимости от реализации, средняя продолжительность TS-фрагмента потока в HLS/DASH может быть от 2 до 15 секунд 31 (EN). В реализации используемой ACME платформы OTT Middleware продолжительность одного фрагмента составляет 8 секунд, а размер TS-фрагмента не превышает 9 MB, в зависимости от выбранного клиентом профиля. Средний размер фрагмента около 2.2 MB.
Учитывая размер фрагмента, имеет смысл включать Jumbo Frame 32, но только на тех серверах, которые коммутируются с сетевым оборудованием с включенным Jumbo Frame.
При подключении сервера к каналообразующему оборудованию через интерфейс 1G необходимо обратить внимание на возможность работы оборудования с Jumbo Frame. Например, некоторые SFP-трансиверы 1000BASE-T 33 (они же SFP-T
), имеют Hardware MTU в 1500 байт и любые попытки задействовать Jumbo Frame на стороне сервера не дадут результатов.
Типовые настройки сетевого интерфейса для CentOS 7:
$ cat /etc/sysconfig/network-scripts/ifcfg-eth0
TYPE="Ethernet"
BOOTPROTO="static"
DEFROUTE="yes"
PEERDNS="no"
PEERROUTES="no"
IPV4_FAILURE_FATAL="no"
IPV6INIT="yes"
IPV6_AUTOCONF="no"
IPV6_DEFROUTE="no"
IPV6_PEERDNS="no"
IPV6_PEERROUTES="no"
IPV6_FAILURE_FATAL="no"
NAME="eth0"
UUID="55084b5b-3a68-4b2d-89c3-833cbf1f73fb"
DEVICE="eth0"
DNS1=198.51.100.6
DNS2=203.0.113.6
DOMAIN="tv.acme.tld"
SEARCH="tv.acme.tld"
ONBOOT="yes"
IPADDR=198.51.100.178
NETMASK=255.255.255.248
GATEWAY=198.51.100.177
MTU=9000
Дополнительно следует увеличить размер очереди передачи сетевого интерфейса txqueuelen 34 (EN) (Transmit Queue Length) до значений, больших значения по умолчанию. К сожалению, классический параметр ETHTOOL_OPTS
не позволяет изменять этот параметр (на 2015 год), поэтому значение txqueuelen
будет задаваться через udev при загрузке ОС:
$ cat /etc/udev/rules.d/50-custom-txqueuelen.rules
KERNEL=="eth*", RUN+="/sbin/ip link set %k txqueuelen 10000"
Не менее важной является корректировка настроек ядра Linux через sysctl 35:
$ cat /etc/sysctl.conf
# Максимальное количество file-handlers, которое система сможет утилизировать
fs.file-max=100000
# Использовать полный диапазон портов
net.ipv4.ip_local_port_range = 1024 65535
# Выключить быструю утилизацию сокетов в состоянии TIME_WAIT.
net.ipv4.tcp_tw_recycle = 0
# Разрешить переиспользовать уже существующие сокеты в состоянии TIME_WAIT
net.ipv4.tcp_tw_reuse = 1
# По 16MB на сокет для передачи и приёма данных
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
# Максимальное число запоминаемых запросов на соединение,
# для которых не было получено подтверждения от клиента
net.ipv4.tcp_max_syn_backlog = 4096
# Включает SYN Cookies, защита от SYN флуда
net.ipv4.tcp_syncookies = 1
# Максимальное количество "backlogged" сокетов
net.core.somaxconn = 2048
# Максимальное количество пакетов, взятое со всех интерфейсов за один цикл поллинга
net.core.netdev_budget = 600
# Отключить TCP Selective Acknowledgments (SACK) для высокопроизводительной сети
net.ipv4.tcp_sack = 0
# Изменить приёмные буферы для сокетов
net.ipv4.tcp_rmem = 16384 349520 16777216
Очень важно держать параметр net.ipv4.tcp_tw_recycle
выключенным, иначе пользователи не смогут смотреть контент одновременно с нескольких устройств с одного IP.
Все логи Nginx шлёт по syslog
на хост msk-cache-analytics01.acme.tld. Эта функциональность появилась в общедоступном Nginx появилась в версии 1.7.1.
На всех серверах групп CDN Precache и CDN Cache используется tmpfs 36 для размещения кешируемых Nginx файлов. Для CDN Cache’ров:
$ grep tmpfs /etc/fstab
tmpfs /var/cache/nginx/ram tmpfs defaults,nodev,nosuid,size=7G 0 0
Для CDN Precache’ров:
$ grep tmpfs /etc/fstab
tmpfs /var/cache/nginx/ram tmpfs defaults,nodev,nosuid,size=14G 0 0
Monit: CDN Cache, CDN Precache
Основой текущей реализации CDN ACME является Nginx и от стабильности его работы зависит качество услуги. Несмотря на то, что используется стабильная ветка Nginx, в продуктивных системах могут происходить коллизии. В качестве локального сервиса слежения за работоспособностью Nginx выбран Monit из-за своей компактности и нетребовательности к ресурсам системы.
$ sudo monit status
The Monit daemon 5.14 uptime: 4d 22h 9m
Process 'nginx'
status Running
monitoring status Monitored
pid 991
parent pid 1
uid 0
effective uid 0
gid 0
uptime 4d 22h 9m
children 5
memory 1.4 MB
memory total 24.4 MB
memory percent 0.0%
memory percent total 0.3%
cpu percent 0.0%
cpu percent total 9.4%
port response time 0.000s to [127.0.0.1]:80 type TCP/IP protocol DEFAULT
data collected Tue, 03 May 2016 23:09:57
System 'msk-cache-01.tv.acme.tld'
status Running
monitoring status Monitored
load average [0.36] [0.47] [0.49]
cpu 3.7%us 7.8%sy 0.0%wa
memory usage 269.9 MB [3.3%]
swap usage 0 B [0.0%]
data collected Tue, 03 May 2016 23:09:57
Monit работает на localhost:2812
, доступ к управлению разрешён с localhost:
$ cat /etc/monit.d/monit
set httpd port 2812 and
use address localhost
allow localhost
Параметры мониторинга Nginx включают:
- Отсылку сообщений о событиях в рассылку
monit@acme.tld
- Перезапуск Nginx в случае отсутствия ответов по адресу
127.0.0.1:80
- Перезапуск до 2 раз в случае загрузки vCPU более 40%, при отсутствии изменений после перезапусков посылается email
- Перезапуск до 5 раз в случае загрузки vCPU более 60%, при отсутствии изменений после перезапусков посылается email
- Если прошло более 10 перезапусков в 10 циклах, мониторинг Nginx отключается
$ cat /etc/monit.d/nginx # nginx check process nginx with pidfile /run/nginx.pid start program = "/usr/bin/systemctl start nginx.service" stop program = "/usr/bin/systemctl stop nginx.service" noalert monit@acme.tld if failed host 127.0.0.1 port 80 then restart if cpu is greater than 40% for 2 cycles then alert if cpu > 60% for 5 cycles then restart if 10 restarts within 10 cycles then timeout
logrotate: CDN Cache
Так как все Access лог-файлы шлются на удалённый сервер msk-cache-analytics01.acme.tld
, а локально на CDN Cache’рах хранится только информация о кешировании, нет большого смысла хранить эти лог-файлы более двух дней:
$ cat /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily
missingok
rotate 1
compress
delaycompress
notifempty
create 644 nginx adm
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
endscript
}
Nginx: CDN Cache
Точкой входа пользовательского трафика в CDN являются CDN Cache’ры. Настройки Nginx этих серверов выглядят следующим образом:
$ cat /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
log_format cache '$upstream_cache_status';
log_format CDN '{"ip": "$remote_addr", "host": "$host", "path": "$request_uri", "status": "$status", "user_agent": "$http_user_agent", "length": $bytes_sent, "date": "$time_iso8601"}';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
proxy_cache_path /var/cache/nginx/ram keys_zone=ram:10m inactive=1m max_size=6656m;
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
server_name _;
location / {
root /usr/share/nginx/html;
return 403;
}
}
}
Модификации подвергся параметр worker_rlimit_nofile
, изменяющий ограничения на максимальное число открытых файлов для рабочих процессов. Дополнительно был создан новый формат лога CDN
, формирующий лог в формате JSON. Создана кеш-область в RAM максимальным размером в 6.5 GB параметром proxy_cache_path
. Данные в кеше удаляются каждую минуту при отсутствии обращений к ним.
Также стоит обратить внимание на формат логирования cache
, который записывает в лог только содержимое переменной $upstream_cache_status
. Этого значения достаточно для дальнейшего подсчёта cache hit ratio.
$ cat /etc/nginx/conf.d/CDN.conf
upstream cdn.tv.acme.tld {
# msk-precache-01.tv.acme.tld
server 198.51.100.162:80;
# msk-precache-02.tv.acme.tld
server 198.51.100.166:80;
# msk-vs-01.tv.acme.tld
server 192.0.2.56:80 backup;
# msk-vs-02.tv.acme.tld
server 192.0.2.57:80 down;
}
upstream pvr01-cdn.tv.acme.tld {
# msk-precache-01.tv.acme.tld
server 198.51.100.162:80;
# msk-precache-02.tv.acme.tld
server 198.51.100.166:80;
}
upstream pvr02-cdn.tv.acme.tld {
# msk-precache-01.tv.acme.tld
server 198.51.100.162:80;
# msk-precache-02.tv.acme.tld
server 198.51.100.166:80;
}
map $http_host $upstreamSet {
hostnames;
pvr01-cdn.tv.acme.tld "pvr01-cdn.tv.acme.tld";
pvr01-cdn.tv.acme.tld:80 "pvr01-cdn.tv.acme.tld";
pvr02-cdn.tv.acme.tld "pvr02-cdn.tv.acme.tld";
pvr02-cdn.tv.acme.tld:80 "pvr02-cdn.tv.acme.tld";
default "cdn.tv.acme.tld";
}
server {
listen 80;
server_name pvr01-cdn.tv.acme.tld pvr02-cdn.tv.acme.tld cdn.tv.acme.tld;
# msk-cache-analytics01.acme.tld
access_log syslog:server=203.0.113.221:514,facility=local7,tag=nginx,severity=info CDN;
access_log /var/log/nginx/cache.log cache;
error_log /var/log/nginx/error.log;
location ~* \.(m3u8)$ {
proxy_cache off;
expires -1;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://$upstreamSet;
}
location / {
index plst.m3u8;
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
proxy_cache ram;
proxy_cache_key $host$uri;
proxy_cache_valid 5m;
proxy_temp_path /var/cache/nginx/ram/temp;
proxy_store_access user:rw group:rw all:r;
proxy_method GET;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://$upstreamSet;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
В конфигурации виртуального хоста CDN Cache’ра для выбора upstream группы задействован механизм map, который подставляет в proxy_pass
в переменную $upstreamSet
требуемые значения. Виртуальный сервер обслуживает имена pvr01-cdn.tv.acme.tld
, pvr02-cdn.tv.acme.tld
, cdn.tv.acme.tld
. Access лог-файлы шлются на удалённый хост msk-cache-analytics01.acme.tld
по протоколу syslog. Файлы m3u8 не кешируются, остальные файлы кешируются на 5 минут. Ключом занесения файла в кеш является $host$uri
, так как часть $query_string
видоизменяется в процессе жизни элемента HLS/DASH потока. Дополнительно переписывается поле Connection
и включается HTTP/1.1 для задействования механизма Keep-Alive
, позволяя сократить количество соединений между пользовательским устройством и CDN Cache’ром, а также между CDN Cache’ром и CDN Precache’ром.
Особое внимание стоит обратить на блок map, в котором присутствуют описания хостов как с указанием порта, так и без. Это решение требуется для iOS (iPhone, iPad), которая по умолчанию в заголовок Host при запросе подставляет порт, даже если это 80 порт.
Nginx: CDN Precache
Само появление CDN Precache’ров обязано лицензионным ограничениям платформы OTT Middleware по гигабитам трафика с Origin Streamer’ов. Nginx на CDN Precache’рах отрабатывает логику отказоустойчивости решения, выбора Origin Streamer’а и распределения трафика между ними по разного вида услугам:
- Live
- VoD и Catch-Up
- PVR
Основная конфигурация Nginx на CDN Precache’ре практически не отличается от таковой на CDN Cache’ре:
$ cat /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
events {
worker_connections 2048;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
log_format CDN '{"ip": "$remote_addr", "host": "$host", "path": "$request_uri", "status": "$status", "user_agent": "$http_user_agent", "length": $bytes_sent, "date": "$time_iso8601"}';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
proxy_cache_path /var/cache/nginx/ram keys_zone=ram:10m inactive=1m max_size=13824m;
include /etc/nginx/conf.d/*.conf;
}
Отличия заключаются в размере кеша в 13.5 GB
и отсутствии default виртуального хоста. Основная конфигурация:
$ cat /etc/nginx/conf.d/CDN.conf
upstream cdn.tv.acme.tld {
# msk-vs-01.tv.acme.tld
server 192.0.2.56:80;
# msk-vs-02.tv.acme.tld
server 192.0.2.57:80 down;
keepalive 1024;
}
upstream pvr01-cdn.tv.acme.tld {
# msk-vs-01.tv.acme.tld
server 192.0.2.56:80;
}
upstream pvr02-cdn.tv.acme.tld {
# msk-vs-02.tv.acme.tld
server 192.0.2.57:80;
}
map $http_host $upstreamSet {
hostnames;
pvr01-cdn.tv.acme.tld "pvr01-cdn.tv.acme.tld";
pvr02-cdn.tv.acme.tld "pvr02-cdn.tv.acme.tld";
default "cdn.tv.acme.tld";
}
server {
listen 80 default_server;
server_name _;
access_log off;
error_log /var/log/nginx/msk-precache-01.tv.acme.tld.error.log;
location ~* \.(m3u8)$ {
proxy_cache off;
expires -1;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_403 http_404;
proxy_pass http://$upstreamSet;
}
location / {
index plst.m3u8;
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
proxy_cache ram;
proxy_cache_key $host$uri;
proxy_cache_valid 5m;
proxy_temp_path /var/cache/nginx/ram/temp;
proxy_store_access user:rw group:rw all:r;
proxy_method GET;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_403 http_404;
proxy_pass http://$upstreamSet;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
Применяются все те же приёмы, которые использовались для CDN Cache’ров, но теперь upstream группы содержат лишь хосты Origin Streamer’ов.
PVR и виртуальные кластеры OTT Middleware
Для разделения PVR 37 каналов по отдельным стримерам и более гибкого масштабирования услуг реализованы виртуальные кластеры:
- pvr01-cdn.tv.acme.tld
- pvr02-cdn.tv.acme.tld
pvr01-cdn.tv.acme.tld
привязан к msk-vs-01.tv.acme.tld
Origin Streamer’у, а pvr02-cdn.tv.acme.tld
- к msk-vs-02.tv.acme.tld
. Это позволяет разнести пользовательскую нагрузку между Origin Streamer’ами по услуге PVR, так как услуга PVR вызывает большую IO на дисковую подсистему Origin Streamer’ов, и, при необходимости, осуществить резервирование услуг по отдельности.
При запросе PVR контента Service Gateway sgw.tv.acme.tld
в составе OTT Middleware (msk-sgw-01.tv.acme.tld
и msk-sgw-02.tv.acme.tld
) отдаёт абоненту в плейлисте ссылку pvr01-cdn.tv.acme.tld
или pvr02-cdn.tv.acme.tld
, в зависимости от того, на каком Origin Streamer’е находится контент. Абонент обращается на общий адрес CDN cdn.tv.acme.tld
и попадает на CDN Cache’ры, далее запрос проксируется на CDN Precache’ры. CDN Precache’ры согласно настроенным правилам перенаправляют запрос по доменному имени либо на msk-vs-01.tv.acme.tld
, либо на msk-vs-02.tv.acme.tld
.
Мониторинг
Внимание:
В 2022 году имеет смысл рассмотреть альтернативы Zabbix, например, Prometheus. Все изображения в тексте соответствуют таковым для 2016 года.
Для мониторинга характеристик CDN используется Zabbix с агентом на хостах. С каждого CDN Cache’ра и CDN Precache’ра помимо стандартных метрик, дополнительно снимаются метрики утилизации кеша Nginx, общее количество дискового пространства кеша Nginx, эффективность кеширования.
Создан хост cdn.tv.acme.tld
с суммирующими данные с CDN Cache’ров/CDN Precache’ров элементами данных:
CDN
Из суммируемого элемента данных по входящему трафику:
и суммируемого элемента данных по исходящему трафику:
строится основной график потребления трафика в CDN:
Помимо общего графика для CDN, созданы общие региональные графики CDN. По ним можно оценивать количество трафика с региона или наличие коллизий с предоставлением сервиса в регионе.
Существует и общий суммирующий график утилизации Cache в CDN:
Cache Hit Ratio
Для всех CDN Cache’ров снимаются значения Cache Hit Ratio в процентном отношении:
$ cat /etc/zabbix/zabbix_agentd.d/userparams.conf
UserParameter=cache.ratio[*],echo "scale=2; $(/bin/grep HIT /var/log/nginx/cache.log | /usr/bin/wc -l)*100/$(/bin/grep -v -- - /var/log/nginx/cache.log | /usr/bin/wc -l)" | /usr/bin/bc
По снятым значениям для каждого CDN Cache’ра строится график:
Origin
Не менее важным является график трафика из/в Origin Streamer’ы, так как лицензирование платформы определяется количеством гигабит, потребляемых с Origin Streamer’ов:
График строится идентичным образом из двух суммирующих элементов данных: элемента данных входящего трафика с CDN Precache’ров:
и элементов данных исходящего трафика с CDN Precache’ров:
Помимо этого, с каждого Origin Streamer’а снимаются значения по объёмам трафика услуг Live/PVR/VoD:
Диагностика
Внимание:
В 2022 году для хранения логов имеет смысл отказаться от Syslog в пользу более гибких инструментов. Например, связка Nginx JSON logs + Fluentd + Apache Kafka + ClickHouse позволяет получить обработку логов в режиме реального времени и эффективное по месту хранение.
Для облегчения диагностики работоспособности CDN логи с CDN Cache’ров шлются на хост msk-cache-analytics01.acme.tld
по протоколу syslog
.
В качестве примера простейшей диагностики можно рассмотреть поиск по IP клиента CDN Cache’ра, который с 21 до 22 часов вечера приземлял трафик пользователя услуги PVR на платформе iOS:
$ grep 198.18.18.140 /var/log/remote/2016/05/15/*_21_access.log | grep -i pvr | grep -i apple | head -5
/var/log/remote/2016/05/15/msk-cache-03.tv.acme.tld_21_access.log:{"ip": "198.18.18.140", "host": "pvr01-cdn.tv.acme.tld", "path": "/pvr/id119_ACME_SG--tnt/02/c_1162603100204372.ts", "status": "200", "user_agent": "AppleCoreMedia/1.0.0.13E238 (iPad; U; CPU OS 9_3_1 like Mac OS X; ru_ru)", "length": 1350008, "date": "2016-05-15T21:02:34+03:00"}
/var/log/remote/2016/05/15/msk-cache-03.tv.acme.tld_21_access.log:{"ip": "198.18.18.140", "host": "pvr01-cdn.tv.acme.tld", "path": "/pvr/id119_ACME_SG--tnt/02/c_1162603100204373.ts", "status": "200", "user_agent": "AppleCoreMedia/1.0.0.13E238 (iPad; U; CPU OS 9_3_1 like Mac OS X; ru_ru)", "length": 1130888, "date": "2016-05-15T21:02:36+03:00"}
/var/log/remote/2016/05/15/msk-cache-03.tv.acme.tld_21_access.log:{"ip": "198.18.18.140", "host": "pvr01-cdn.tv.acme.tld", "path": "/pvr/id119_ACME_SG--tnt/01/plst.m3u8?chanId=119&startDate=15052016113500&endDate=15052016133500&curPos=15052016113500", "status": "200", "user_agent": "AppleCoreMedia/1.0.0.13E238 (iPad; U; CPU OS 9_3_1 like Mac OS X; ru_ru)", "length": 35920, "date": "2016-05-15T21:02:37+03:00"}
/var/log/remote/2016/05/15/msk-cache-03.tv.acme.tld_21_access.log:{"ip": "198.18.18.140", "host": "pvr01-cdn.tv.acme.tld", "path": "/pvr/id119_ACME_SG--tnt/01/c_1162603100204004.ts", "status": "200", "user_agent": "AppleCoreMedia/1.0.0.13E238 (iPad; U; CPU OS 9_3_1 like Mac OS X; ru_ru)", "length": 861207, "date": "2016-05-15T21:02:37+03:00"}
/var/log/remote/2016/05/15/msk-cache-03.tv.acme.tld_21_access.log:{"ip": "198.18.18.140", "host": "pvr01-cdn.tv.acme.tld", "path": "/pvr/id119_ACME_SG--tnt/02/plst.m3u8?chanId=119&startDate=15052016113500&endDate=15052016133500&curPos=15052016113500", "status": "200", "user_agent": "AppleCoreMedia/1.0.0.13E238 (iPad; U; CPU OS 9_3_1 like Mac OS X; ru_ru)", "length": 35920, "date": "2016-05-15T21:02:38+03:00"}
Пользователь с IP 198.18.18.140
на устройстве Apple iPad
с русскоязычной версией iOS 9.3.1
, смотревший PVR канала ТНТ, приземлялся на сервере msk-cache-03.tv.acme.tld
. Дополнительно можно сказать, учитывая информацию об имени PVR сервера, что пользователь уходил на Origin Streamer msk-vs-01.tv.acme.tld
.
Для удобства чтения JSON-логов Nginx на сервере msk-cache-analytics01.acme.tld
предустановлена утилита jq 38 (EN).
$ grep -h 198.18.18.140 /var/log/remote/2016/05/15/*_21_access.log | grep -i pvr | grep -i apple | head -1 | jq .
{
"ip": "198.18.18.140",
"host": "pvr01-cdn.tv.acme.tld",
"path": "/pvr/id119_ACME_SG--tnt/02/c_1162603100204372.ts",
"status": "200",
"user_agent": "AppleCoreMedia/1.0.0.13E238 (iPad; U; CPU OS 9_3_1 like Mac OS X; ru_ru)",
"length": 1350008,
"date": "2016-05-15T21:02:34+03:00"
}
Ссылки
1. Content Delivery Network ↩
2. Over the Top ↩
3. Internet Service Provider ↩
4. Связующее программное обеспечение ↩
5. Автономная система ↩
6. Acme Corporation ↩
7. Обороты в минуту ↩
8. Network File System ↩
9. Streaming Packagers
[EN] ↩
10. M3U формат ↩
11. NGINX-based VOD Packager [EN] ↩
12. RAM ↩
13. BGP Anycast ↩
14. CentOS [EN] ↩
15. Red Hat Enterprise Linux [EN] ↩
16. CentOS Stream [EN] ↩
17. Nginx ↩
18. The BIRD Internet Routing Daemon [EN] ↩
19. Monit [EN] ↩
20. Zabbix ↩
21. Видео по запросу ↩
22. Cache Hit Ratio [EN] ↩
23. Prometheus [EN] ↩
24. What’s HTTP Live Streaming [EN] ↩
25. Border Gateway Protocol ↩
26. Bidirectional Forwarding Detection [EN] ↩
27. Универсальные платформы маршрутизации серии MX ↩
28. BGP Multipath [EN] ↩
29. 8b/10b Encoding [EN] ↩
30. 64b/66b Encoding [EN] ↩
31. Optimal Adaptive Streaming Formats MPEG-DASH & HLS Segment Length
[EN] ↩
32. Jumbo-кадр ↩
33. Gigabit Ethernet ↩
34. Queueing in the Linux Network Stack [EN] ↩
35. Sysctl утилита ↩
36. Файловой хранилище tmpfs ↩
37. Цифровой видеорекордер ↩
38. Command-line JSON processor jq [EN] ↩