Дмитрий Грошев, Фёдор Гоголев. erlang и haskell в production:...
DESCRIPTION
В докладе рассматривается мотивация и опыт перехода процесса разработки API с большим количеством внутренней логики с Python на сочетание Erlang и Haskell, проблемы в процессе разработки и способы их решения.TRANSCRIPT
.
......
Erlang и Haskell в production: проблемы ирешения
Dmitry Groshev (@lambdadmitry),Fedor Gogolev (@knsd),
@Selectel
FProg 2012-10
04.10.2012
1 / 36
.. Общий план
I ВступлениеI Коротко о пониI YAWNDBI Selecon-webI Коротко об облакахI RainbowdashI TwilightsparkleI Резюме
2 / 36
Вступление
3 / 36
.. Вступление
I 1.5 года production-experience с ErlangI 1 год с HaskellI In-memory timeseries database (YAWNDB)I Система нотификации (Spike)I Веб-консоль (Selecon-web)I Облако (Rainbowdash/Twilightsparkle)
4 / 36
Коротко о пони
5 / 36
..
YAWNDB
7 / 36
.. YAWNDB — Yet Another Weel iNvented
I Timeseries данные (утилизация CPU per second)I Много операций записи (десятки тысяч в секунду —виртуальных машин много)
I Хочется аггрегацию (max/min/avg за период)I Graphite медленный, RRD не умеет аггрегацию
8 / 36
.. YAWNDB
......
requesthandler 1
.
requesthandler 2
.
...
.
requesthandler N
.
Pathmanager
.
New path
.
path 1
.
path 2
.
path 3
.
...
.
path M
.
Disk
.
Dumper
9 / 36
.. YAWNDB
......
requesthandler 1
.
requesthandler 2
.
...
.
requesthandler N
.
Pathmanager
.
New path
.
path 1
.
path 2
.
path 3
.
...
.
path M
.
Disk
.
Dumper
10 / 36
.. YAWNDB: выводы
I NIF (Native Implemented Functions) это круто, но опасноI мутабельные NIF binaries предоставляют изолированнуюмутабельность
I писать NIF неприятно, документация полна, но не всегдапомогает
I property-based тестирование при использовании NIFнеобходимо, т.к. ошибки нетривиальны (C же!), а segfault'ытравматичны
I fuzz-тесты на случайных/бессмысленных данных полезныI писать высококонкурентные системы сложно, Erlang недобавляет сложности
I устойчивость к ошибкам Erlang'а помогает, в продакшнепочти полгода был редкий рейс без последствий вообще
11 / 36
.. YAWNDB: выводы 2I код лаконичен (650 строк на C, 1500 строк на Erlang'е)I если вы пишите что-то сетевое, нет ни одной причины неиспользовать Cowboy
I если ваш проект длиннее 30 строк, нет ни одной причины неиспользовать gproc
I поддержка SMP Erlang'ом не миф
12 / 36
.. YAWNDB: ссылки
I Graphite https://github.com/graphite-projectI Ecirca https://github.com/band115/ecircaI Cowboy https://github.com/extend/cowboyI Cowboy https://github.com/uwiger/gprocI McErlang https://github.com/fredlund/McErlang
13 / 36
Облака
14 / 36
..
.. Об облаках
Xen:I Dom0, DomUI запуск и остановка доменовI простой и неубиваемый
XAPI (XenAPI) от Citrix:I МиграцияI ПулыI Динамическое управление памятьюI ...
16 / 36
.. Больше, чем XAPI
I учёт используемых ресурсов (биллинг, статистика)I управление машинами из биллинга, веб-интерфейса, API иадминистраторами
I детекция нештатных ситуаций (падение хранилища либосети)
I динамическая балансировка нагрузкиI предоставление интерфейсов к машине, непредусмотренных XAPI (web-консоль, realtime потребление,MemoryOnDemand)
Много сложной «бизнес»-логики
17 / 36
.. Старая архитектура
I Make it work, make it right, make it fastI Python+Bash помойкаI Коммуникация через HTTP, Mongo и redis (aka «какполучится»)
I WTF is summationd? WTF is yawndbtiond-obsolete?I боль с Python+Mongo — много раздельного кода,размазывание схемы
18 / 36
.. Новая архитектура
I Make it work, make it right, make it fastI Построение «от API»I VBD/VDI/VIF/BDSM → Disk/Network interface/...I Фиксированная схема данныхI Erlang для сети и рантайма, Haskell для «бизнес»-логикиI Механизм Erlang ports — stdin/stdout + Erlang External TermFormat
19 / 36
.. Новая архитектура
..RainbowDash.Happy
customer. Twilight
Sparkle.
TwilightSparkle
.
TwilightSparkle
. LegacyMongo
.
PostgreSQL
.
XAPI
20 / 36
Rainbowdash
21 / 36
..
.. Rainbowdash
I Милая, быстрая, немного простоватая, но reliable для друзейI REST + RPC: HTTP REST API → RPC API на фронтенде поконфигу с верификацией (type safety!)
I Асинхронность + синхронность: интерфейс синхронный,rainbowdash асинхронна, twilightsparkle синхронна
I «Задачи» с уникальным идентификатором для каждогозапроса
I 2-phase commit задачи: проверка корректности и ожидаемойресурсоёмкости, запуск (возможно, отложенный)
I балансировка нагрузки на бекендах по ожидаемым ресурсами внешним характеристикам процессов (ping, mem)
I отчёты о состоянии системы (ping, mem, cpu, rps, latency)I 2-phase commit конфигаI почти live reloading Haskell-кода с персистентными задачамии HTTP-коннектами
23 / 36
.. Rainbowdash: выводы
I переход программистов Python → Erlang занимаетнеделю-полторы
I запаковка не-Erlang кода с помощью rebar это боль(Make+bash+cabal+cabal-dev)
I jobs — прекрасная библиотека, но документации почти нетI любить себя полезно, несколько часов на автоматизациюперезагрузки бекенда при изменении бинарника окупилисьмногократно
I кода до первой работоспособной версии достаточно мало(1k строк)
24 / 36
.. Rainbowdash: ссылки
I jobs https://github.com/uwiger/jobs/
25 / 36
Twilightsparkle
26 / 36
..
.. TwiligthSparkle
I Общая архитектураI Template Haskell и генерация сервераI Контроль ошибок на уровне типовI Барьеры — откат измененийI Persistent ORMI Проблемы при разработке
28 / 36
.. TwiligthSparkle: общая архитектура
I Сервер, занимающийся чтением запросов из stdin и пишущийответы в stdout
I Используется стандартный для Эрланга способкоммуникации — порты
I Был написан модуль реализующий ETF (External Term Format)I Воркеры, выполняющиеся в отдельных процессахI Сложное ядро, максимально простой API для написаниянепосредственно обработчиков запросов
I Каждый запрос определяется тремя параметрами: source,input и result
I source — Источник задачи, в нашем случае это пользовательAPI, администратор или внутренний сервис
I input — Входные данные запросаI result — Результат на выполнение запроса
class TaskSource source => Task source input result
29 / 36
..TwiligthSparkle: Template Haskell и генерациясервера
Template Haskell используется для генерации функций разборазапросов от сервера. Например из кода:
[erlServer|vm_start :: TS User VMStartTask ()
|]
генерируется код:dispatch ref "vm_start"
(ErlTuple [ErlBinary "user", ErlInt userId])inputV = case fromErl inputV of
Nothing -> invalidTaskJust (i :: VMStartTask) -> do
... -- Process requestdispatch ref "vm_start" _user _input = invalidTask
30 / 36
.. TwiligthSparkle: Контроль ошибок
I Прерывание выполнения подобно ErrorT трансформеруI Отдельные типы для каждого вида ошибокI Требование явного декларирования списка возможныхошибок
instance AllowError source VMStartTask () VMNotFoundinstance AllowError source VMStartTask () VMIsAlreadyRunning
I Пока нет, но хочется контроль декларированных и невызываемых ошибок
31 / 36
.. TwiligthSparkle: Барьеры
I Существует необходимость отката изменений в случаеошибок
I Барьеры устанавливаются после изменения, для котороготребуется откат и выполняются в случае возникновенияошибки
vm <- createVmbarrier $ destroyVm vmdisk <- createDiskbarrier $ destroyDisk diskerror "Any error"
I Технически реализовано как [TS source input result ()] внутриTVar контекста ReaderT
32 / 36
.. TwiligthSparkle: Persistent ORM
I Первая версия не использовала ORM
vm@(VM { vmUuid, vmTemplate }) <-fetch VMCollection [ "id" =: iVmId ]
I Регулярно возникали опечатки в названиях полей, впередаваемых данных
I Для Хаскеля нет рабочих альтернативных ORM кромеpersistent
vm@(VM { vmUuid, vmTemplate }) <- fetch [ VmId ==. iVmId ]
I Пришлось использовать патченную версиюpersistent-mongodb, так как модель хранения отличается отподразумеваемой разработчиками
33 / 36
.. TwiligthSparkle: Проблемы при разработке
I Space leaksI Очень трудно найти источник проблемы при большом объёмекода
I Не хватает некоторых пакетов на hackage, либо неустраивает их состояние
I Написали библиотеку для работы с ETFI Стали поддерживать библиотеки bson и mongoDB
I Вероятно, более высокий порог вхожденияI Тем не менее в проект, кроме ядра, успешно пишутпрограммисты без какого-либо функционального бэкграунда
34 / 36
.. TwiligthSparkle: Выводы
I Заметно упало количество не логических ошибок, например:I Параметризованные идентификаторы, например (UUID VM),не допускают их использование для не VM объектов
I Отдельные типы для различных семантически данных,например DiskSize
I Template Haskell — позволяет удобно решать проблемы, нокатастрофически плохо читается
I Использовать cabal-dev — очень хорошая идея
35 / 36
Вопросы?
36 / 36
Copyrighted stuff:https://en.wikipedia.org/wiki/File:Cirrus_sky_panorama.jpghttp://www.wallpapervortex.com/wallpaper-15684_1_other_wallpapers_my_little_pony.htmlhttp://www.tikihumor.com/3287/rainbow-dash-makes-it-rain/rainbow-dash-makes-it-rain-2/http://qeinone.deviantart.com/art/Twilight-Sparkle-205789859
37 / 36