Хабрахабр

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

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

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

Фаза хайпа

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

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

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

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

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

Эта теория получила широкое распространение в 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». Люди будут заниматься культом карго, и успешные проекты будут плодить подражателей.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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 до сих пор мало и его потенциал не раскрыт.

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»