4 года разрабатывает видеостриминговый сервер эрливидео и в этом докладе расскажет о некоторых отличительных возможностях Erlang, которые позволяют быстро развиваться и поддерживать высочайшее качество ПО минимальными усилиями.
3. • Бизнесу нужен продукт, а не софт
• Программистам интересно писать софт
• Нет опыта в продакшне, значит небезопасно
делать продукт на таком софте
• Бизнес избегает ФП
• Без коммерческого применения нет опыта
• Замкнутый цикл
6. Эрливидео
• Высоконагруженный видеостриминговый сервер
(10 ГБит/с без проблем)
• 5 лет разработки и успешной продажи ПО
• Беспроблемный найм людей
• Очень мало критичных багов (и те в C)
• Крайне быстрая разработка
• Без эрланга мы бы не справились!
7. Эрланг в продакшне
• Надежно
• Дешево
• Предсказуемо
• Имеет смысл использовать для коммерческого
софта
8. Продакшн познается через
год
• Софт дорастает до использования живыми
пользователями
• Начинается поддержка старого кода
• Приходят новые программисты, перед которыми
стыдно за исходники
• Пользователи создают нагрузку
9. Проблемы эксплуатации
• Работа со своим и чужим кодом
• Работа с багами на недевелоперских серверах
• Поведение под нагрузкой
10. Поддержка старого кода
• Через год даже свой код уже не вспомнить
• Автора кода не достать, он пошел на IPO
• Статической типизации в эрланге нет
11. Реалии старого кода
• Код 10-летней давности запускается и работает
• Очень сильная обратная совместимость между
версиями VM
• Немутабельность сильно помогает отладке
• Не-OTP код — зло, OTP код — хорошо
12. Старый код в Эрливидео
• Есть куски кода, которым по 5 лет
• Иногда проводятся массовые рефакторинги
• Интеграционные тесты помогают, юнит-тесты нет
13. Борьба с багами
• 95% падений рантайма — нехватка памяти
• Нехватка памяти почти всегда — нехватка
контроля за пайплайном данных
• Остальное лечится чтением стектрейсов сверху
вниз, потому что let it fail
• Если пишем хорошо, то ошибки изолируются по
процессам
14. Алгоритмы багфикса
• По нажатию кнопки «загрузить логи», система
сама пакует всё
• Пользователи всегда вырезают самое
интересное из логов, их логи мы не читаем
• Изучаем стектрейсы и периодический дамп
самых прожорливых процессов
• Пытаемся восстановить ситуацию у себя. Если не
можем, идем на сервер заказчика
15. Авральные работы на
сервере
• recon, htop в помощь что бы понять, какой ресурс
сожран
• to_erl дает больший контроль, чем другие варианты
(remsh и ssh)
• erlang:processes() что бы найти самого обжору
• ищем причину утечки памяти и/или тормозов
• непроходимость в пайплайне данных -> утечка
памяти
16. Интроспекция
• supervisor:which_children/1 для обхода структуры
• sys:get_state/1 что бы добраться до нутра
• lager:pr/2 для изучения состояния
• lager:md/1 для тегирования логов
• самодельные хелперы: ems_debug:top(binary)
17. Само-мониторинг
• На сервера не набегаешься
• Система должна сама себя мониторить
• Поиск источника багов
• Поиск потенциальных тормозов (для highload)
18. Мониторинги
• Потребление памяти (раз в 10 секунд)
• Мониторинг длин очередей
• Мониторинг размера ets таблиц
• Внутренние очереди
• Контроль за тем, что данные втекают не быстрее,
чем вытекают
19. Capacity control
• Что бы не лопнуть, надо уметь отказываться
• Поиск утечек памяти и багов показывает
бутылочные горлышки
• Узкие места должны сообщать о собственной
загрузке
• Без обратного контроля можно быстро, но
недолго
20. Работа под нагрузкой
• Эрланг — одна из нескольких multicore
платформ
• Можно получить линейное ускорение по ядрам
• Интроспекция на живом продакшне под полной
нагрузкой
• Как всё не затормозить?
21. Шаги на пути к Highload
• Развязывание узких мест: одно ядро не может, а
10 смогут
• Ускорение линейного кода
• Перенос данных в память
22. Развязывание узких мест
• Singleton это узкое место, потому что одно ядро
• gen_server:call сам по себе не спасает
• Нужно разносить однопроцессные сервисы на
несколько ядер
• Способы: пулы, шардирование, ets
• ETS — это очень быстро и эффективно
23. Примеры
распараллеливания
• У одного открытого файла пул процессов,
читающих с диска
• В comet сервере шардинг процессов
мониторинга по hash(channel_id) % pool_size
• Подписка через ets типа bag: по ключу много
значений сразу
24. Профилирование
• Возможность профилировать отдельный процесс
• В эрланге оно всё так себе
• Анализ стектрейсов
• Тайминги в заголовках HTTP ответов
• Не особо много хитростей
25. ETS для памяти
• In-memory database
• Великолепно масштабируется на 40-70 ядер
• Прекрасно годится для отдачи готовых данных
• Рекомендуется вместе с zerocopy протоколами
• Вторичные индексы руками
26. Примеры в Эрливидео
• Раздача live потоков: данные готовятся заранее,
укладываются в ets таблицы. 20 Гбит/с без
надрыва
• Стриминг файлов с диска: пляски с бубном и
10-15 Гбит/с можно
27. Архитектура стриминга с
диска
• В линуксе синхронное чтение с диска, тред на запрос.
• Держим 50 или 1000 одновременных запросов к диску
• Процесс файла — арбитр между динамическим пулом
процессов ридеров
• Ридеры идут в лимитированную очередь с таймаутом: N
одновременных запросов и M в ожидании
• Мониторинг загрузки диска и времени чтения
• Спасибо POSIX API
28. Продакшн
• Писать код на Эрланге интересно
• Возможно устранять баги в бою
• Можно поддерживать старый код и жить с ним
• Можно делать крайне производительный код,
притом очень быстро