[Перевод] Десять лет программирования на Erlang

d08c3507ef04c305f0934e703b35bf53.png


Я присоединился к сообществу Erlang около 10 лет назад, посреди первой фазы хайпа. Нам говорили, что Erlang — это будущее конкурентности и параллелизма. Реализовать их на этом языке проще и быстрее всего, и вы ещё получите бесплатную распределённость. В то время будущее казалось невероятным. Виртуальная машина недавно получила поддержку SMP, но чтобы действительно использовать все процессоры, приходилось запускать на одном компьютере несколько виртуальных машин.

Я хочу поразмышлять о прошедшем десятилетии. В этой статье я расскажу о фазах хайпа в отношении Erlang, о лестнице идей в языке и о её возможном влиянии на распространение языка, о том, через какие перемены я прошёл за эти 10 лет. И в заключение поделюсь своими мыслями о том, что Erlang ещё предстоит привнести в сообщество программистов в целом.

Фаза хайпа


Цикл хайпа состоит из фаз жизненного цикла продукта или технологии. Это маркетинговая концепция, а не научная, но частенько помогает в описании сути происходящего. Больше всего меня интересует фаза хайпа, своеобразная золотая лихорадка, накрывающая сообщества программистов. Возможно, вы не раз с этим сталкивались, и все эти фазы связаны с каким-нибудь killer app, которое все бросаются использовать.

Из примеров сразу приходят на ум Ruby on Rails, How to Build a Blog Engine in 15 minutes (фраза «Посмотрите на всё то, что я не делаю!» всё ещё смешная) или Go с Kubernetes (они и до этого работали вместе, а потом был прямо всплеск). Сюда же можно отнести и Elixir с Phoenix.

Во время фазы хайпа наблюдается невероятный приток новичков, которые хотят посмотреть, из-за чего вся суета. Кто-то остаётся, большинство уходят. Вы можете остаться на месяцы или годы, в редких случаях вы находите себе дом на десятилетия. Однако подавляющее большинство — это постоянный поток серийных людей, которые скачут от технологии к технологии, выискивая возможности получения выгоды за счёт того, что они первыми используют фреймворк, язык или набор инструментов.

Так что чаще всего вам нужно сделать одно настоящее «убойное приложение», и люди потянутся в вашу экосистему. Убойное приложение подстёгивает ажиотаж. Если вы его напишете, они к вам придут. И если вы сможете удержать небольшую долю из них и сохранить их активность, то у вас будет живое сообщество в течение обозримого будущего. Это, в какой-то степени напоминает идею дождя, следующего за плугом:

Господь подгоняет плуг.… Вслед за этим чудесным приспособлением, которое является единственным владычеством человека над природой, облака проливают обильные дожди… [плуг] — это инструмент, отделяющий цивилизацию от варварства, он превращает пустыню в фермы и сады. … Короче говоря, дождь следует за плугом.

Суть теории заключалась в том, что проживание людей и сельское хозяйство оказывают необратимое воздействие на климат засушливых и полузасушливых районов, делая эти регионы более влажными. Эта теория получила широкое распространение в 1870-х годах как оправдание заселения Великих равнин — региона, ранее известного как «Великая американская пустыня». В те же годы эта теория использовалась для оправдания расширения посевов пшеницы на малоплодородных территориях землях в Южной Австралии.

Если мы сможем запустить большой проект, то появятся разработчики, и он станет самодостаточным. Я считаю эту идею однозначно ошибочной, в основном потому, что в ходе самой большой фазы хайпа у Erlang были десятки убойных приложений, однако сообщество до сих пор маленькое. Вот примеры этих приложений:

  • ejabberd (2002, первый стабильный релиз в 2005-м): это был один из самых, если не самый масштабируемый чат-сервер. Ejabberd добился большого успеха, и в какой-то мере он ещё актуален. Сегодня на StackOverflow ещё встречаются вопросы про модули для этого сервера. Примерно в 2011-м его форкнули в MongooseIM, и оба решения до сих пор поддерживаются.
  • CouchDB (2005): одна из самых популярных баз данных, написанных на Erlang, в основе которой лежала теорема CAP. Относится к тем временам появления мультимастер-хранилищ. Хотя основную долю рынка заняла MongoDB, у CouchDB есть духовные наследники среди движков хранилищ, вроде BarrelDB, который тоже до сих пор поддерживается.
  • RabbitMQ (2007): сервер очередей сообщений, подмявший под себя большую часть рынка AMQP. Он развивается и часто конкурирует с Kafka, когда речь заходит о потоковых нагрузках, хотя у этих продуктов разные возможности и сферы применения.
  • Facebook chat (2008): начальная версия Facebook Chat была написана на Erlang. По ряду внутренних причин (стабильность, большое количество программистов на С++ и ряд устоявшихся решений) был позднее переписан на С++.
  • WhatsApp (2009, куплен в 2014-м): когда Facebook избавился в системе чатов от Erlang, они купили WhatsApp, для поддержки которого требовалось всего 50 инженеров на 900 миллионов пользователей. Он живёт по сей день, и более того, команда WhatsApp ещё больше укрепила связи с сообществами Erlang и Elixir.
  • Riak (2009): один из лучших примеров демонстрации силы в мире распределённых систем. Riak был надёжным распределённым хранилищем типа «ключ-значение». Это продукт Basho, который до сих пор работает в системах здравоохранения и других критически важных частях инфраструктуры. Позднее Basho обанкротились (в немалой степени благодаря нарушениям фидуциарных обязанностей, которые «на всех парах привели компанию к краху»). Затем Bet365 выкупила все их IP, великодушно открыла их, и с тех пор БД живёт в мире open source, хотя сегодня она переживает не лучшие времена.


Многие из этих продуктов вышли во времена первого тиража книги Джо Армстронга Programming Erlang. В результате возник настоящий шторм внедрения языка, а Erlang обрёл много почитателей. Значительное влияние оказало даже то, что Hacker News форсили все обсуждения по Innards of Erlang. Тем не менее, мало кто остался верен этому языку.

Теперь я считаю, что убойные приложения создаются людьми, которые формируют начальную фазу хайпа, а не наоборот. Всегда существует небольшая часть людей, которые раньше других выискивают интересные технологии, решают, нравятся ли они им, затем что-то создают, и если получается киллер апп, то это стимулирует развитие ещё более мощной фазы хайпа. Люди будут заниматься культом карго, и успешные проекты будут плодить подражателей. Также стандартной ситуацией является фаза «изобретения колеса», когда все тратят своё время на переизобретение уже существующих вещей, и возникает волна сообщений о «реализации X, но на языке Y».

Однако мало просто создать killer app. Любопытно, что у всех этих продуктов, вроде RabbitMQ и Ejabberd, несмотря на всю их популярность, сообщество пользователей гораздо больше, чем сообщество разработчиков. Тысячи и тысячи корпораций, использующие эти продукты, вовсе не обязательно вносят заметный вклад в сообщество Erlang.

Частично это связано с тем, что большинство убойных приложений Erlang используются в специализированных инфраструктурах. Вы создали высоконадёжный компонент в виде чёрного ящика, которым все пользуются, и если он работает хорошо, то никто не заглянет внутрь. Несколько десятков разработчиков предоставили основу для тысяч других продуктов и сервисов. Специализированная инфраструктура по определению не нуждается в большом количестве людей, чтобы обеспечить её широкое влияние. У неё всегда немного разработчиков и небольшое сообщества по сравнению с технологиями, которые находятся ближе к конечному продукту, например, веб-фреймворки, или ещё более обобщённые инфраструктуры, которые используются в небольших проектах для деплоя, подходящих для любой компании.

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

Лестница идей


Я не стану разглагольствовать о том, что могло или должно было быть сделано. Вместо этого я хочу поговорить о популярных паттернах изучения, которые я встречал в сообществе Erlang за годы моего преподавания этого языка и программирования на нём. Эти же паттерны я сегодня наблюдаю в сообществе Elixir, и это может свидетельствовать об аналогичном будущем для него.

У меня есть теория, что такая техническая тема, как язык программирования (и его экосистема), имеет несколько уровней сложности, на которых расположены разные концепции. Я использовал эту теорию в проекте Learn You Some Erlang. Она представлена на диаграмме, которую я назвал Девять кругов Эрла.

Конечно, это ироническая идея, я не считаю, что изучение какой-то технологии — это бесконечное страдание (по крайней мере, так не должно быть). Мне просто понравился каламбур. Попросту говоря, всегда существует какой-то «основной» путь или последовательность тем, которые вы познаёте при изучении технологии — это «лестница идей», и чем выше расположена концепция на этой лестнице, тем она ценнее и тем труднее в достижении, тем меньше людей познают её.

Как может выглядеть лестница идей в Erlang:

  1. Функциональное программирование.
  2. Изолированные процессы и конкурентность.
  3. Надёжная конкурентность (ссылки, мониторы, таймауты).
  4. Принципы OTP и другие системные абстракции.
  5. Как структурировать системы по принципам OTP.
  6. Как собирать релизы и работать с ними (деплой).
  7. Как не допускать падения системы и работать с ней.


Если вы только знакомитесь с Erlang и купили книгу для начинающих, то наверняка первые дни потратите на первую ступень лестницы: ознакомление с функциональным программированием, неизменяемостью (иммутабельность), рекурсией и прочими подобными концепциями. Рано или поздно вы доберётесь до конкурентности и паралеллизма, процессов и передачи сообщений. Сразу после них вы начнёте изучать ссылки и мониторы, обработку сбоев и то, что делает Erlang тем, что он есть. Во время большой фазы хайпа на второй и третьей ступенях находились возможности, которые для большинства наблюдателей выглядели просто невероятно. Если вам нужно было научиться чему-то, что вы будете использовать во всех будущих проектах, то вы могли выбрать одну из этих возможностей Erlang.

На другие ступени можно было подняться позже, но только если вы будете придерживаться программы обучения по ступеням. В частности, OTP (четвёртая ступень) можно охарактеризовать как «о чём это всё вообще». Конкурентность и функциональное программирование — это хорошо, но общий фреймворк, представленный с помощью OTP, был действительно уникален, и его нужно было использовать. Со временем многие поработают с ним, обнаружат, что могут создавать классные абстракции, но им не понравится подход к структурированию.

По сути, для создания приложений вроде Ejabberd достаточно было преодолеть четвёртую ступень. В те времена экосистема напоминала Дикий Запад, и знанием OTP владели специалисты, работавшие в Ericsson, а также самые мотивированные самоучки. Большинство никогда не достигали пятой ступени, если только не отправляли что-то в production и не сталкивались после этого с проблемами, или если они не искали решение получше. Достижение шестой ступени было редкостью до 2015–2016, а потом появился Relx, упростивший сборку релизов и их освоение. До седьмой ступени почти никто не добрался, и куча людей считает, что не следуют выполнять горячее обновление ноды Erlang, и, в идеале, для отладки в production никогда не понадобится использовать SSH.

На практике, не все проходят по лестнице идей в том же порядке, её ступени в некоторых книгах поменяны местами (например, в Erlang and OTP in Action). В этом нет ничего плохого, лестница придумана всего лишь как иллюстрация.

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

Думаю, подняться на первые три ступени Erlang было легко. Для подъёма на четвёртую нужно было заниматься разработкой несколько лет, да и вообще чтобы почувствовать необходимость дальнейшего изучения. На пятой ступени уже очень сложно. Инструментарий и экосистема Erlang были бедны. Участники сообщества терпели эту бесплодную среду, и были равнодушны к тяжёлому положению новичков. Чтобы сделать статью короче (ну, длинной, но не абсурдно длинной), посмотрите моё выступление об экосистеме языка на конференции Erlang User Conference:


Если вы пишете на Elixir, то, вероятно, видите, на какой ступени этой выдуманной лестницы вы стоите, и уже можете представить, в каких долях по ней распределено сообщество. Многие участники прекрасно владеют одним лишь Phoenix, но редко поднимаются выше четвёртой ступени, а многие застревают на третьей и ниже. И часто этого достаточно. Я не осуждаю, а лишь делюсь наблюдением. Как любой, кто поднялся на много ступеней (и наверняка здесь передо мной ещё несколько ступеней, вроде «патчинга виртуальной машины» или чего-то другого), я вижу, что эти люди многого не знают. Но, честно говоря, вся эта информация может быть для них бесполезной. И это хорошо.

О чём я хочу сказать: я считаю, что мы, как сообщество, вероятно, пилим под собой сук, делая лестницу идей очень трудной в освоении выше базового уровня. Некоторые темы нужно изучать неторопливо, а в некоторых темах слепые ведут слепых, потому что Erlang так мал, что у нас просто слишком мало людей, которые могут поделиться всем необходимым опытом. Сегодня с этим попроще, и если вы пришли в Erlang не в фазу хайпа, то наверняка получите помощь, поскольку её одновременно просят гораздо меньше людей.

Хотелось бы думать, если завтра в мире Erlang начнётся вторая фаза хайпа, то мы сможем принять новичков лучше, чем во времена большой волны, когда пришёл и я. И надеюсь, этот опыт вкупе с более тесным сотрудничеством сообществ Erlang и Elixir удвоит наши шансы на успешное расширение использования этих языков.

Что изменилось


Erlang не плавает заспиртованный в колбе, ожидая, когда его вытащат на свет. Он постоянно развивается. Отчасти это обусловлено конкуренцией и пожеланиями со стороны сообщества Elixir, которое, к счастью, ожидает от своих инструментов куда большего, чем то, к чему привыкли пользователи Erlang. И отчасти развитие обусловлено актуальными потребностями индустрии и пожеланиями академического сообщества.

Думаю, кто-то будет рад этим изменениям, произошедшим с 2009-го или даже ранее:

  • Многоядерная поддержка теперь работает хорошо. Раньше, если ядер было больше 2–4, система упиралась во всевозможные узкие места, которые не были подвластны разработчику приложения. Затем стало возможно использовать 12–16 ядер. Сегодня я даже не знаю, какой верхний предел, но я писал и управлял стеками, которые работали более чем на 32 ядрах безо всяких проблем.
  • В стек-трейсах теперь есть номера строк. Почти немыслимо вернуться в прошлое, до появления номеров. В те годы «написание коротких самодокументированных функций» было вопросом не архитектуры, а выживания. Теперь вы можете отлаживать программы на Erlang без сверхъестественных навыков отладки, хотя они никогда не повредят.
  • Появилась поддержка Unicode стала вполне удовлетворительной. Модуль string содержит все важные алгоритмы, а модуль unicode прекрасно обрабатывает большинство преобразований и нормализаций. Существуют общие стратегии для работы с сырыми элементами кодового пространства (codepoints) — UTF-8, UTF-16 и UTF-32. Поддержки местных языков пока нет, но возможность есть. Модули вроде re (для регулярных выражений) и весь код обработки файлов более высокого уровня также хорошо работают с Unicode.
  • Поддерживаются мапы (maps) (реализованы как HAMT) с явным синтаксисом сопоставления паттернов. С помощью Dialyzer к ним применяется анализ типов, что позволяет использовать их в тех случаях, в которых раньше использование записей требовало больших усилий.
  • В виртуальных машинах теперь применяются отличные механизмы работы со временем, они справляются с изменением масштаба времени, разными типами часов и прочим. Однако работать с часовыми поясами и форматировать время лучше с помощью библиотек, разработанных сообществом.
  • Добавлены такие высокопроизводительные инструменты, как atomics, counters и persistent terms, они помогают улучшать различные механизмы, лежащие в основе средств наблюдения и низкоуровневых базовых библиотек.
  • Вся обработка сигналов стала асинхронной, включая работу с портами, что избавило нас от многих узких мест.
  • Компилятор был переписан и всё ещё переписывается, чтобы повысить высокоуровневый анализ и производительность с помощью SSA.
  • Теперь есть «грязные» (dirty) диспетчеры с NIF, они упростили интеграцию с кодом на С и Rust, при этом поддерживаются IO- или CPU-intensive workloads. Язык стал быстрее, пусть и не многократно, и при этом стало гораздо проще использовать более производительные библиотеки, не слишком сильно влияя на стабильность исполнения.
  • Сделаны разные улучшения в механизме выделения и управления памятью.
  • Анализ работы программы стал точнее и быстрее благодаря более быстрой и гибкой трассировке и учёту микросостояний.
  • Более гибкое OTP-поведение gen_statem позволило реализовать конечные автоматы, способные обрабатывать входные данные выборочно.
  • Новый улучшенный фреймворк журналирования со встроенной поддержкой структурированных журналов.
  • Модуль crypto переписан и использует NIF вместо более сложных (и часто медленнее обновляемых) drivers.
  • Файловый driver полностью переписан с использованием NIF, что очень сильно повысило производительность.
  • Для достижения такой же производительности продолжают переписывать сетевые drivers с применением NIF.
  • Полностью переделано применение SSL для обработки TLS. Когда я работал в Heroku, мы старались сделать так, чтобы продукт был сравним с решениями на С++ по уровню задержки (может, процентов на 5 хуже) и сильно обгонял по прогнозируемости (в 10–30 раз меньше 99-х перцентилей).
  • Значительно улучшена производительность ETS.
  • Я написал руководство по управлению и отладке production-систем на виртуальных машинах Erlang.
  • Совершенно новое средство сборки (rebar3), интегрированное с унифицированным менеджером пакетов для экосистемы Erlang.
  • Теперь в виртуальной машине доступен ряд других языков, с перекрестным использованием библиотек. Среди поддерживаемых языков Elixir, Efene, LFE, Luerl, Clojerl и минимум два языка с выведением типов с Gleam и Alpaca.
  • И много других изменений внутри и вовне основного дистрибутива Erlang.


Если хотите узнать подробнее, почитайте полный список изменений в релизах. А вкратце могу сказать, что если бы команда OTP в Ericsson работала над 13–16 релизами чуть менее интенсивно (а сейчас версия 22!), то их усилия по использованию Erlang в основном продукте были бы очевидны. Впрочем, всё изменяется и за пределами Ericsson. Сообщества Erlang и Elixir, а также участники разработки Erlang VM из других языков объединились, чтобы создать Erlang Ecosystem Foundation, с рабочими группами, которые сейчас помогают координировать и решать проблемы инструментов сборки и упаковки, улучшать наблюдаемость (observability — возможности мониторинга состояния работающей системы), безопасность, и т.д.

Если вы, как и я, были частью большой начальной фазы хайпа, но, в отличие от меня, не задержались на этом языке, потому что многое выглядело непригодным к использованию или запутанным, то, быть может, захотите дать Erlang второй шанс. Удобство и экосистема языка разительно улучшились.

Куда движется Erlang


Быть может, больших убойных приложений больше не появлялось, как это было в 2007–2009, но это не означает, что нет многообещающих проектов. Erlang всё ещё глубоко интегрирован в инфраструктуру многих корпораций, и большинство его изначальных убойных приложений до сих пор используются. К тому же, у нас много интересных новых игроков, как показывает каждая конференция BEAM Conf. Я сам очень увлечён концепциями вроде тестирования на основе свойств (Property-Based Testing), а для Erlang и Elixir созданы одни из лучших фреймворков в мире. И несмотря на всё это, мы не находимся в фазе хайпа. По крайней мере, сейчас.

Будет ли другая такая фаза? Может быть, да, а может быть, нет. Вы можете сказать, что следующей фазой хайпа был Elixir. У экосистем достаточно много общего, чтобы уроки, извлечённые в одной из них, были применены в другой. У обеих экосистем больше сходств, чем различий. Возможно, нас ожидает некий Ренессанс. Лично меня это больше не волнует. Мне нравятся небольшие сообщества, я чувствую себя в низ комфортно. Чтобы любить Erlang, мне не нужен геометрический рост последователей, пусть их количество просто будет стабильным.

Кроме того, размер сообщества никогда не мешал распространению Erlang по миру. Сколько я с ним знаком, язык всегда был в таком положении, что не хватает задач для всех Erlang-программистов, и не хватает программистов для всех Erlang-задач: много и тех, и других, но географически они не всегда совпадают. Лучше всего поступают корпорации и работники, которые выходят на удалённые рынки труда.

И если раньше Erlang не мог легко проникнуть на рынок веб-приложений, то сейчас с минимальными доработками ему открыт весь рынок Elixir-задач.

Вероятно, для общей картины мира не слишком важно, используете ли вы язык вроде Erlang или нет. Хотя мне кажется, что он недооценён и мог бы применяться шире. Главное преимущество Erlang не в том, чтобы использовать именно его. Главное преимущество в изучении основ проектирования надежных систем, а также в практическом применении полученных знаний.

За эти годы постоянно слышны вопросы, связанные с изучением. Как научиться проектировать протоколы? Что посоветуете почитать про создание распределенных систем? Как потрудиться, но сделать что-то очень надёжное и отказоустойчивое? Как понять, что моя архитектура модульная, и мои абстракции не протекают? Что такое хорошая обработка ошибок? Как узнать, что оптимизация преждевременна? Что означает «сделать что-то декларативным»?

Мы любим короткие и удобоваримые решения, вроде книг рецептов и лучших методик, но настоящие ответы представляют собой вариацию «за последние годы я узнал». Честно скажу, что за мою карьеру ничто не сравнится с пребыванием в сообществе Erlang и впитыванием опыта его ветеранов. Сообщество невелико, но богато по всем остальным критериям. За несколько лет я из junior перешёл на senior-роли, выступал по всему миру, искал способы передачи своего опыта, и по большей части, всё это благодаря сообществу.

Быть может, я ещё не могу за 15 минут написать движок для блога (по правде говоря, я вообще медленно разрабатываю), но зато я очень быстро стал гораздо сильнее как разработчик и системный архитектор. Опять же, меня всегда влекло не использование систем, а их создание и доведение до рабочего состояния. У всех своя мотивация.

Я не могу представить, что получил бы столь же много в другом сообществе. Эти 10 лет были потрясающими. Любопытно, что сообщество Erlang до сих пор мало и его потенциал не раскрыт. Это означает, что есть много возможностей поучаствовать во всём, пообщаться один на один с людьми, полными мудрости и желающими поделиться ею, и найти свое место.

© Habrahabr.ru