استفاده از TSDuck برای نظارت بر جریان های IP (TS).

امروزه راه حل های آماده (اختصاصی) برای نظارت بر جریان های IP (TS) وجود دارد، به عنوان مثال VB и iQ، آنها مجموعه ای از عملکردهای نسبتاً غنی دارند و معمولا اپراتورهای بزرگی که با خدمات تلویزیون سروکار دارند چنین راه حل هایی دارند. این مقاله راه حلی را بر اساس یک پروژه منبع باز توضیح می دهد TSDuckطراحی شده برای حداقل کنترل جریان های IP(TS) توسط شمارنده CC (کنترل شمارنده) و میزان بیت. یک کاربرد ممکن، کنترل از دست دادن بسته ها یا کل جریان از طریق یک کانال L2 اجاره شده است (که به طور معمول نمی توان آن را کنترل کرد، به عنوان مثال، با خواندن شمارنده های تلفات در صف ها).

به طور خلاصه در مورد TSDuck

TSDuck یک نرم افزار متن باز (مجوز BSD 2-Clause) (مجموعه ای از ابزارهای کنسول و کتابخانه ای برای توسعه ابزارها یا پلاگین های سفارشی) برای دستکاری جریان های TS است. به عنوان ورودی، می تواند با IP (multicast/unicast)، http، hls، تیونرهای dvb، dektec dvb-asi demoulator کار کند، یک ژنراتور داخلی TS-stream و خواندن از فایل ها وجود دارد. خروجی می تواند نوشتن روی یک فایل، IP (multicast/unicast)، hls، dektec dvb-asi و مدولاتور HiDes، پخش کننده (mplayer، vlc، xine) و drop باشد. پردازنده‌های ترافیک مختلفی را می‌توان بین ورودی و خروجی گنجاند، به‌عنوان مثال، نقشه‌برداری مجدد PID، درهم‌زدایی/جلوگیری، تحلیل شمارنده CC، محاسبه نرخ بیت و سایر عملیات‌های معمولی برای جریان‌های TS.

در این مقاله از جریان های IP (مولتی کست) به عنوان ورودی، پردازنده bitrate_monitor (از نام مشخص است که چیست) و پیوستگی (تحلیل شمارنده های CC) استفاده می شود. شما به راحتی می توانید IP multicast را با نوع ورودی دیگری که توسط TSDuck پشتیبانی می شود جایگزین کنید.

وجود دارد ساخت/بسته های رسمی TSDuck برای اکثر سیستم عامل های فعلی. آنها برای دبیان در دسترس نیستند، اما ما موفق شدیم آنها را تحت دبیان 8 و دبیان 10 بدون هیچ مشکلی بسازیم.

در مرحله بعد، نسخه TSDuck 3.19-1520 استفاده می شود، لینوکس به عنوان سیستم عامل استفاده می شود (دبیان 10 برای تهیه راه حل استفاده شد، CentOS 7 برای استفاده واقعی استفاده شد)

آماده سازی TSDuck و OS

قبل از نظارت بر جریان های واقعی، باید مطمئن شوید که TSDuck به درستی کار می کند و هیچ افتی در سطح کارت شبکه یا سیستم عامل (سوکت) وجود ندارد. این مورد نیاز است تا بعداً حدس نزنیم که ریزش ها کجا اتفاق افتاده است - در شبکه یا "داخل سرور". می توانید با دستور ethtool -S ethX افت در سطح کارت شبکه را بررسی کنید، تنظیم توسط همان ethtool انجام می شود (معمولاً باید بافر RX (-G) را افزایش دهید و گاهی اوقات برخی از بارگذاری ها (-K) را غیرفعال کنید). به عنوان یک توصیه کلی، می توان توصیه کرد که از یک پورت جداگانه برای دریافت ترافیک تجزیه و تحلیل شده استفاده کنید، در صورت امکان، این موارد مثبت کاذب مربوط به این واقعیت است که افت دقیقاً در پورت تحلیلگر به دلیل وجود ترافیک دیگر اتفاق افتاده است. اگر این امکان پذیر نباشد (از یک مینی کامپیوتر/NUC با یک پورت استفاده می شود)، بسیار مطلوب است که اولویت بندی ترافیک تجزیه و تحلیل شده را نسبت به بقیه در دستگاهی که آنالایزر به آن متصل است تنظیم کنید. در مورد محیط های مجازی، در اینجا شما باید مراقب باشید و بتوانید قطرات بسته را پیدا کنید که از یک پورت فیزیکی شروع می شود و به یک برنامه در داخل ماشین مجازی ختم می شود.

تولید و دریافت یک جریان در داخل میزبان

به عنوان اولین گام در آماده سازی TSDuck، ما ترافیک را در یک هاست با استفاده از netns تولید و دریافت خواهیم کرد.

آماده سازی محیط:

ip netns add P #создаём netns P, в нём будет происходить анализ трафика
ip link add type veth #создаём veth-пару - veth0 оставляем в netns по умолчанию (в этот интерфейс будет генерироваться трафик)
ip link set dev veth1 netns P #veth1 - помещаем в netns P (на этом интерфейсе будет приём трафика)
ip netns exec P ifconfig veth1 192.0.2.1/30 up #поднимаем IP на veth1, не имеет значения какой именно
ip netns exec P ip ro add default via 192.0.2.2 #настраиваем маршрут по умолчанию внутри nents P
sysctl net.ipv6.conf.veth0.disable_ipv6=1 #отключаем IPv6 на veth0 - это делается для того, чтобы в счётчик TX не попадал посторонний мусор
ifconfig veth0 up #поднимаем интерфейс veth0
ip route add 239.0.0.1 dev veth0 #создаём маршрут, чтобы ОС направляла трафик к 239.0.0.1 в сторону veth0

محیط آماده است. تحلیلگر ترافیک را شروع می کنیم:

ip netns exec P tsp --realtime -t 
 -I ip 239.0.0.1:1234 
 -P continuity 
 -P bitrate_monitor -p 1 -t 1 
 -O drop

که در آن "-p 1 -t 1" به این معنی است که شما باید نرخ بیت را در هر ثانیه محاسبه کنید و اطلاعات مربوط به بیت ریت را در هر ثانیه نمایش دهید.
ما مولد ترافیک را با سرعت 10 مگابیت در ثانیه راه اندازی می کنیم:

tsp -I craft 
 -P regulate -b 10000000 
 -O ip -p 7 -e --local-port 6000 239.0.0.1:1234

که در آن "-p 7 -e" به این معنی است که شما باید 7 بسته TS را در 1 بسته IP بسته بندی کنید و آن را به سختی (-e) انجام دهید، یعنی. همیشه قبل از ارسال بسته IP منتظر 7 بسته TS از آخرین پردازنده باشید.

تحلیلگر شروع به خروجی پیام های مورد انتظار می کند:

* 2020/01/03 14:55:44 - bitrate_monitor: 2020/01/03 14:55:44, TS bitrate: 9,970,016 bits/s
* 2020/01/03 14:55:45 - bitrate_monitor: 2020/01/03 14:55:45, TS bitrate: 10,022,656 bits/s
* 2020/01/03 14:55:46 - bitrate_monitor: 2020/01/03 14:55:46, TS bitrate: 9,980,544 bits/s

حالا چند قطره اضافه کنید:

ip netns exec P iptables -I INPUT -d 239.0.0.1 -m statistic --mode random --probability 0.001 -j DROP

و پیام هایی مانند این ظاهر می شود:

* 2020/01/03 14:57:11 - continuity: packet index: 80,745, PID: 0x0000, missing 7 packets
* 2020/01/03 14:57:11 - continuity: packet index: 83,342, PID: 0x0000, missing 7 packets 

که انتظار می رود. از دست دادن بسته را غیرفعال کنید (ip netns exec P iptables -F) و سعی کنید نرخ بیت ژنراتور را به 100 مگابیت بر ثانیه افزایش دهید. تحلیلگر تعداد زیادی خطای CC و حدود 75 مگابیت بر ثانیه را به جای 100 گزارش می دهد. ما در تلاش هستیم تا بفهمیم مقصر چه کسی است - ژنراتور وقت ندارد یا مشکل در آن نیست، برای این ما شروع به تولید تعداد ثابتی می کنیم. بسته ها (700000 بسته TS = 100000 بسته IP):

# ifconfig veth0 | grep TX
       TX packets 151825460  bytes 205725459268 (191.5 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
# tsp -I craft -c 700000 -P regulate -b 100000000 -P count -O ip -p 7 -e --local-port 6000 239.0.0.1:1234
* count: PID    0 (0x0000):    700,000 packets
# ifconfig veth0 | grep TX
        TX packets 151925460  bytes 205861259268 (191.7 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

همانطور که می بینید، دقیقا 100000 بسته IP تولید شد (151925460-151825460). بنابراین بیایید بفهمیم که با تحلیلگر چه اتفاقی می‌افتد، برای این کار با شمارنده RX در veth1 بررسی می‌کنیم، کاملاً برابر با شمارنده TX در veth0 است، سپس به آنچه در سطح سوکت می‌افتد نگاه می‌کنیم:

# ip netns exec P cat /proc/net/udp                                                                                                           
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode ref pointer drops             
  133: 010000EF:04D2 00000000:0000 07 00000000:00000000 00:00000000 00000000     0        0 72338 2 00000000e0a441df 24355 

در اینجا می توانید تعداد افت ها را ببینید 24355. در بسته های TS، این 170485 یا 24.36٪ از 700000 است، بنابراین می بینیم که همان 25٪ از بیت ریت از دست رفته افت هایی در سوکت udp هستند. افت در سوکت UDP معمولاً به دلیل کمبود بافر رخ می دهد، به اندازه بافر پیش فرض سوکت و حداکثر اندازه بافر سوکت نگاه کنید:

# sysctl net.core.rmem_default
net.core.rmem_default = 212992
# sysctl net.core.rmem_max
net.core.rmem_max = 212992

بنابراین، اگر برنامه‌ها صریحاً اندازه بافر درخواست نکنند، سوکت‌هایی با بافر 208 کیلوبایتی ایجاد می‌شوند، اما اگر بیشتر درخواست کنند، باز هم آنچه درخواست شده را دریافت نمی‌کنند. از آنجایی که می‌توانید اندازه بافر را در tsp برای ورودی IP تنظیم کنید (-buffer-size)، ما اندازه سوکت پیش‌فرض را لمس نمی‌کنیم، بلکه فقط حداکثر اندازه بافر سوکت را تنظیم می‌کنیم و اندازه بافر را به صراحت از طریق آرگومان‌های tsp مشخص می‌کنیم:

sysctl net.core.rmem_max=8388608
ip netns exec P tsp --realtime -t -I ip 239.0.0.1:1234 -b 8388608 -P continuity -P bitrate_monitor -p 1 -t 1 -O drop

با این تنظیم بافر سوکت، اکنون میزان بیت گزارش شده حدود 100 مگابیت در ثانیه است، هیچ خطای CC وجود ندارد.

با توجه به مصرف CPU خود برنامه tsp. نسبت به CPU یک هسته ای i5-4260U @ 1.40GHz، تجزیه و تحلیل جریان 10Mbps به 3-4٪ CPU، 100Mbps - 25٪، 200Mbps - 46٪ نیاز دارد. هنگام تنظیم % Packet Loss، بار روی CPU عملا افزایش نمی یابد (اما ممکن است کاهش یابد).

در سخت افزار پربازده تر، امکان تولید و تجزیه و تحلیل جریان های بیش از 1 گیگابیت در ثانیه بدون هیچ مشکلی وجود داشت.

تست روی کارت های شبکه واقعی

پس از آزمایش روی یک جفت veth، باید دو هاست یا دو پورت یک هاست را بگیرید، پورت ها را به یکدیگر متصل کنید، ژنراتور را روی یکی و تحلیلگر را در دومی راه اندازی کنید. در اینجا هیچ شگفتی وجود نداشت، اما در واقع همه چیز به آهن بستگی دارد، هرچه ضعیف تر باشد، اینجا جالب تر خواهد بود.

استفاده از داده های دریافتی توسط سیستم مانیتورینگ (Zabbix)

tsp هیچ API قابل خواندن ماشینی مانند SNMP یا مشابه ندارد. پیام های CC باید حداقل برای 1 ثانیه جمع شوند (با درصد بالایی از دست دادن بسته ها، بسته به میزان بیت می تواند صدها / هزاران / ده ها هزار در ثانیه باشد).

بنابراین، برای ذخیره اطلاعات و رسم نمودار برای خطاهای CC و میزان بیت و ایجاد نوعی تصادف، ممکن است گزینه های زیر وجود داشته باشد:

  1. خروجی tsp را تجزیه و جمع کنید (با CC) یعنی. آن را به فرم دلخواه تبدیل کنید.
  2. خود و/یا پلاگین های پردازنده bitrate_monitor و continuity را به پایان برسانید تا نتیجه به شکلی قابل خواندن توسط ماشین مناسب برای سیستم نظارت ارائه شود.
  3. درخواست خود را در بالای کتابخانه tsduck بنویسید.

بدیهی است که گزینه 1 از نظر تلاش ساده ترین است، به خصوص با توجه به اینکه خود tsduck به زبان سطح پایین (با استانداردهای مدرن) (C ++) نوشته شده است.

یک نمونه اولیه Bash Parser+Aggregator ساده نشان داد که در یک جریان 10Mbps و 50٪ از دست دادن بسته (بدترین حالت)، فرآیند bash 3-4 برابر بیشتر از خود فرآیند tsp CPU مصرف می کند. این سناریو غیر قابل قبول است. در واقع یک قطعه از این نمونه اولیه در زیر

رشته فرنگی در بالا

#!/usr/bin/env bash

missingPackets=0
ccErrorSeconds=0
regexMissPackets='^* (.+) - continuity:.*missing ([0-9]+) packets$'
missingPacketsTime=""

ip netns exec P tsp --realtime -t -I ip -b 8388608 "239.0.0.1:1234" -O drop -P bitrate_monitor -p 1 -t 1  -P continuity 2>&1 | 
while read i
do
    #line example:* 2019/12/28 23:41:14 - continuity: packet index: 6,078, PID: 0x0100, missing 5 packets
    #line example 2: * 2019/12/28 23:55:11 - bitrate_monitor: 2019/12/28 23:55:11, TS bitrate: 4,272,864 bits/s
    if [[ "$i" == *continuity:* ]] 
    then
        if [[ "$i" =~ $regexMissPackets ]]
        then
            missingPacketsTimeNew="${BASH_REMATCH[1]}" #timestamp (seconds)
            if [[ "$missingPacketsTime" != "$missingPacketsTimeNew" ]] #new second with CC error
            then
                ((ccErrorSeconds += 1))
            fi
            missingPacketsTime=$missingPacketsTimeNew
            packets=${BASH_REMATCH[2]} #TS missing packets
            ((missingPackets += packets))
        fi
    elif [[ "$i" == *bitrate_monitor:* ]]
    then
        : #...
    fi
done

علاوه بر کندی غیرقابل قبول، هیچ رشته‌ای در bash وجود ندارد، کارهای bash فرآیندهای جداگانه‌ای هستند و من مجبور شدم مقدار missingPackets را هر ثانیه یک بار روی عارضه جانبی بنویسم (هنگام دریافت پیام‌های نرخ بیت که هر ثانیه می‌آیند). در نتیجه بش به حال خود رها شد و تصمیم گرفته شد که یک لفاف (تجزیه کننده + تجمیع کننده) به گلنگ بنویسند. مصرف CPU کد گلانگ مشابه 4-5 برابر کمتر از خود فرآیند tsp است. افزایش سرعت لفاف به دلیل جایگزینی bash با گلانگ حدود 16 برابر شد و در کل نتیجه قابل قبول است (سربار CPU در بدترین حالت 25٪). فایل منبع golang قرار دارد اینجا.

لفاف را اجرا کنید

برای راه اندازی wrapper، ساده ترین الگوی سرویس برای systemd ساخته شد (اینجا). خود wrapper قرار است در یک فایل باینری (go build tsduck-stat.go) واقع در /opt/tsduck-stat/ کامپایل شود. فرض بر این است که شما از golang با پشتیبانی از ساعت یکنواخت (>=1.9) استفاده می کنید.

برای ایجاد یک نمونه از سرویس، باید دستور systemctl enable را اجرا کنید [ایمیل محافظت شده]:1234 سپس با systemctl start اجرا کنید [ایمیل محافظت شده]: 1234.

کشف از Zabbix

برای اینکه zabbix بتواند سرویس های در حال اجرا را کشف کند، این کار انجام می شود تولید کننده لیست گروه (discovery.sh)، در قالب مورد نیاز برای کشف Zabbix، فرض بر این است که در همان مکان - در /opt/tsduck-stat قرار دارد. برای اجرای Discovery از طریق zabbix-agent، باید اضافه کنید فایل conf به دایرکتوری پیکربندی zabbix-agent برای اضافه کردن پارامتر کاربر.

قالب Zabbix

قالب ایجاد شد (tsduck_stat_template.xml) شامل قانون کشف خودکار، نمونه های اولیه آیتم ها، نمودارها و محرک ها است.

چک لیست کوتاه (خوب، اگر کسی تصمیم به استفاده از آن داشته باشد چه می شود)

  1. اطمینان حاصل کنید که tsp بسته ها را در شرایط "ایده آل" رها نمی کند (ژنراتور و تحلیلگر مستقیماً به هم متصل هستند)، در صورت وجود افت، به بند 2 یا متن مقاله در این مورد مراجعه کنید.
  2. حداکثر بافر سوکت را تنظیم کنید (net.core.rmem_max=8388608).
  3. tsduck-stat.go را کامپایل کنید (به ساخت tsduck-stat.go بروید).
  4. الگوی سرویس را در /lib/systemd/system قرار دهید.
  5. خدمات را با systemctl شروع کنید، بررسی کنید که شمارنده ها ظاهر شده اند (grep "" /dev/shm/tsduck-stat/*). تعداد سرویس ها بر اساس تعداد جریان های چندپخشی. در اینجا ممکن است لازم باشد مسیری برای گروه چندپخشی ایجاد کنید، شاید rp_filter را غیرفعال کنید یا مسیری به ip منبع ایجاد کنید.
  6. Discovery.sh را اجرا کنید، مطمئن شوید که json تولید می کند.
  7. پیکربندی عامل zabbix را اضافه کنید، عامل zabbix را مجددا راه اندازی کنید.
  8. قالب را در zabbix آپلود کنید، آن را روی میزبانی که در حال نظارت است و zabbix-agent نصب شده است اعمال کنید، حدود 5 دقیقه صبر کنید، ببینید آیتم ها، نمودارها و محرک های جدیدی وجود دارد یا خیر.

نتیجه

استفاده از TSDuck برای نظارت بر جریان های IP (TS).

برای تشخیص از دست دادن بسته، تقریباً کافی است، حداقل بهتر از عدم نظارت است.

در واقع، "تلفات" CC هنگام ادغام قطعات ویدئویی ممکن است رخ دهد (تا آنجا که من می دانم، اینگونه درج ها در مراکز تلویزیون محلی در فدراسیون روسیه ساخته می شوند، یعنی بدون محاسبه مجدد شمارنده CC)، این باید به خاطر داشته باشید. راه حل های اختصاصی تا حدی این مشکل را با شناسایی برچسب های SCTE-35 (اگر توسط مولد جریان اضافه شود) دور می زنند.

از نظر نظارت بر کیفیت حمل و نقل، عدم نظارت بر جیتر (IAT) وجود دارد. تجهیزات تلویزیون (اعم از تعدیل‌کننده‌ها یا دستگاه‌های پایانی) الزاماتی برای این پارامتر دارند و همیشه نمی‌توان jitbuffer را تا بی‌نهایت باد کرد. و هنگامی که تجهیزات با بافرهای بزرگ در حمل و نقل استفاده می شود و QoS پیکربندی نشده یا به اندازه کافی پیکربندی نشده است که چنین ترافیک بلادرنگی را منتقل کند، جیتر می تواند شناور شود.

منبع: www.habr.com

اضافه کردن نظر