Нагрузка на сервер: почему Go справляется там, где Python задыхается

Сравниваем производительность Icecast, AzuraCast, Python-решений и нашего Go-сервера при 1000+ слушателях.

Когда ваше радио вырастает от «покрутить для друзей» до серьезного проекта с тысячами слушателей, первый вопрос, который встает перед вами: выдержит ли сервер? И здесь начинается самое интересное. Потому что поведение разных решений под нагрузкой — это совсем не то, что написано в их рекламных буклетах.

Я прошел через это сам. Сначала было решение на Python — простое, понятное, быстрое в разработке. Но когда количество слушателей перевалило за 500, процессор начал задыхаться. При 1000 слушателей сервер превращался в кипящий чайник: CPU на 100%, поток прерывается, слушатели жалуются.

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

Мой опыт: Python vs Go

Мое первое решение было написано на Python с использованием Flask и стандартных библиотек. Логика простая: читаем файлы, транскодируем, отдаем слушателям. Для небольшой аудитории работало отлично.

Но на 1000 слушателей случилось вот что:

Почему так произошло? Python — интерпретируемый язык. У него есть GIL (Global Interpreter Lock), который не позволяет выполнять несколько потоков кода одновременно. Даже если вы используете asyncio или многопоточность, настоящей параллельности нет. При 1000 слушателей каждый запрос требует обработки, и интерпретатор просто не справляется.

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

Разница колоссальная. Но как дела у других решений?

Что говорят тесты: Icecast и его возможности

Icecast — это эталон надежности. Он существует десятилетиями и используется на крупнейших радиостанциях мира. Но что насчет производительности?

Но есть нюанс: Icecast не занимается транскодингом. Если вам нужно несколько битрейтов или выравнивание громкости — эти задачи ложатся на Liquidsoap или другие источники. А вот они уже потребляют ресурсы.

В тестах при 12 000 слушателей Icecast начинал терять стабильность — процессор уходил в пики, слушатели отваливались. Но для большинства радиостанций этого более чем достаточно.

«Icecast справляется с тысячами слушателей, если он работает как чистый ретранслятор. Но как только вы добавляете транскодинг, выравнивание громкости или несколько битрейтов — ресурсы начинают уходить на Liquidsoap, а не на Icecast.»

AzuraCast: удобство ценой ресурсов

AzuraCast — это популярное решение, которое оборачивает Icecast и Liquidsoap в красивую админку. Но за удобство приходится платить.

Что это значит для 1000 слушателей? Если у вас один маунт и 1000 слушателей, AzuraCast справится. Но если у вас 5 маунтов с разными битрейтами — нагрузка на CPU будет высокой. Плюс Liquidsoap постоянно транскодирует треки на лету.

В форумах администраторы отмечают, что при активном использовании AutoDJ и нескольких маунтов нагрузка может быть существенной. А если включены дополнительные функции вроде Replaygain на лету или AutoCue — CPU может уходить в пики.

AzuraCast рекомендуют иметь запас по CPU не менее 50%, чтобы избежать троттлинга на облачных хостингах.

Сравнительная таблица: кто и сколько ест

Решение CPU (1000 слушателей) Память (1000 слушателей) Особенности
Icecast (чистый) Минимальный (~2-5%) ~14-20 МБ Только ретрансляция, без транскодинга
Icecast + Liquidsoap Высокий (~10% на маунт) Зависит от числа маунтов Транскодинг на лету
AzuraCast ~10% на маунт + overhead Рекомендуют от 2-4 ГБ Удобная админка, но ресурсоемкая
Python-решение Высокий (~80-100%) Высокая, склонность к утечкам GIL ограничивает масштабирование
Наше Go-решение Низкий (~15-25%) Стабильный (~300-400 МБ) Горутины, оптимизация треков до эфира

Почему Go выигрывает

Переход с Python на Go дал мне не просто улучшение производительности, а качественный скачок. Вот ключевые причины:

1. Компиляция в машинный код

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

2. Легковесные горутины

В Go каждый слушатель — это легковесная горутина (пара килобайт памяти). В Python каждый поток — это мегабайты и ограничение GIL. При 1000 слушателей разница колоссальная.

3. Оптимизация до эфира

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

4. Эффективная работа с памятью

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

Что насчет Icecast? Не факт, что лучше

Я честно признаю: я не проверял Icecast под нагрузкой 1000+ слушателей. По отзывам и тестам, Icecast справляется отлично. Но есть важный нюанс.

Icecast — это только сервер. Он не умеет сам читать файлы, не умеет выравнивать громкость, не умеет транскодировать. Если вам нужен автономный плейлист — вы добавляете Liquidsoap. А Liquidsoap — это уже отдельный процесс, который потребляет ресурсы.

В моем решении всё в одном процессе. И транскодинг, и выравнивание, и расписание, и отдача потока. Один бинарник, одна точка отказа, минимальное потребление.

Более того, есть тесты, где RSAS (альтернативный сервер на C++) показал лучшую производительность, чем Icecast, при 10 000+ слушателей. Icecast начинал терять стабильность при 12 000 слушателей. Go-решение на том же железе держит стабильно больше.

Что нужно для 1000 слушателей

Исходя из моего опыта и данных из поиска, вот примерные потребности для 1000 слушателей при битрейте 128 kbps:

Итог: мое решение на Go — золотая середина

Если подвести итог сравнению:

Я не утверждаю, что Go-решение обязательно лучше Icecast. Icecast проверен десятилетиями, и для многих задач он идеален. Но если вы хотите и функционал, и производительность — если вам нужен транскодинг, выравнивание громкости, расписание, аналитика, админка — то DIY радио на Go дает всё это в одном флаконе, без умножения процессов и без просадок при росте аудитории.

Мой путь от Python к Go показал: правильный выбор языка и архитектуры — это разница между сервером, который «еле дышит» при 500 слушателях, и сервером, который «спит» при 1000. И я сделал свой выбор.

Готовы к тысячам слушателей?

DIY Радио на Go, которое не падает под нагрузкой. Проверено на 1000+ слушателей.

Попробовать радио на Go