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