Там не только в синтаксисе грабли разложены, в stdlib и plug тоже есть чудесные вещи. Мне хочется написать об этом пост, но он получается какой-то очень гневный, не очень длинный и вообще руки не доходят.
Но в целом, несмотря на все грабли, писать удобнее и даже поприятнее.
Так, между нами, я ведь обращал внимание кого-то из разработчиков портала на этот долбаный скрипт, когда он был еще просто 404 и просто мешался, и мы как-то раз это даже выясняли, что за скрипт и чей он.
Вот только удалить его забыли/забили.
Нет. Kotlin на порядок выразительнее. Go это скорее такая Java 1 — ужасно топорная, но приносящая некоторые широко известные в узких кругах фичи широкой аудитории разработчиков.
Там не только внутренняя сеть, там еще по возможности оптимизированное взаимодействие erlang-нод. При использовании erlang distribution «в лоб», без хитростей, уже 100 нод будет проблемой.
У WhatsApp, если мне не изменяет память, что-то вроде 11000 ядер на порядка 500 машин. Не помню точные числа, но о сравнимых по масштабу инсталляциях я больше не знаю.
> мы решили попробовать что-то новенькое.
Пару лет назад решили, а сейчас уже разговор идет о результатах. Эксперимент уже удался, советы не особо актуальны.
> простота и красота кода, которая в результате повышает продуктивность
Маркетинговый буллщит.
> Erlang совершенно точно ценят не за простоту,
> вспомним хотя бы парадигму функционального программирования.
Erlang не является функциональным ЯП, абсолютно точно. Тут есть пара комментариев, по которым заметна ошибочность и вредность этого подхода.
HOF, иммутабельность и pattern matching уже далеко распространились за пределы ФП.
И да, в посте отмечено, что Erlang — простой.
> склочности Erlang комьюнити
Нет никакой склочности. Вы приходите к людям, которые знают, что делают, и пытаетесь продать им что-то ненужное. Какой вы реакции ждали?
> хабр не получил какой то статьи
Замечательно. На хабре уже более чем достаточно go-фанбоев, хватит.
Позволю себе излишне обобщить — все присутствующие знают и Erlang, и Go, и прекрасно знают, что и когда применять. И то, что если нужно делать сетевые сервисы в масштабах Wargaming, выигрывает именно Erlang, при всех его недостатках, все тоже знают.
Упырьте мел, тут нет фанбоев, это же не пост про Go.
А еще я допустил терминологическую неточность — вместо
«в ets — in-memory-таблице, позволяющей доступ из нескольких процессов»
должно быть написано
«в ets — in-memory-таблице, позволяющей доступ из нескольких акторов». Первая формулировка, кажется, может ввести читателя в заблуждение.
> можно распределять программу на несколько серверов
Можно, но это уже не новичковый уровень. Я, честно говоря, никогда не испытывал нужды в Erlang distribution, поэтому знаю о нем очень мало, штука довольно неоднозначная. Скажем, WhatsApp используют его, но они и умеют его правильно готовить.
По моему опыту, вызывающая сторона чаще всего делает не where, а find_or_start, в котором и прячется внезапный рейс. А так как вызвающая сторона — процесс, с которым общается клиент, это чревато получением клиентом ошибки.
Это примерно такая же частая ошибка новичков, как упомянутый в статье дедлок gen_server:call.
Конечно, я не агитирую против использования ETS, я просто предостерегаю от необдуманого использования.
Вкратце, про рейс — если старт регистрируемого процесса происходит не в процессе-регистраторе, мы можем попасть в ситуацию, когда мы стартовали два инстанса регистрируемого процесса, один успешно регистрируется, попытка регистрации второго приводит к ошибке already_registered. Решается, насколько мне известно, только синхронным запуском процессов через регистратор, причем, я не уверен, является ли gproc:reg_or_locate/3 правильной реализацией.
Ну, этот ets спрятан в процессе-регистраторе, и его может и не быть. Может, в нем для простоты map хранится.
А без процесса-регистратора все равно не выйдет, потому что без него получается классический race condition «регистрация после старта».
Ладно, может и выйдет, но я не могу так навскидку представить, как это реализовать.
ets не всегда нужен, иногда достаточно отдельного процесса с кэшем, который логически располагается между, условно, БД и процессом-обработчиком запроса.
Возьмем для простоты обработку HTTP-запросов с пользовательскими сессиями.
Наиболее распространенная на сегодняшний день модель — у нас есть N воркеров в виде независимых процессов, по ним round robin распределяются запросы пользователей. Все вроде бы работает, но для хранения сессии между запросами нам нужно либо прикреплять пользователей к воркерам, что не очень удобно, либо иметь некое внешнее хранилище для всех сессий — собственно, redis или memcached.
В erlang подход несколько другой — мы запускаем один процесс ОС, в рамках которого на N ОС-тредах выполняется куча легковесных процессов(акторов), которые и выполняют пользовательские запросы. Причем, на каждый запрос создается новый актор, который умирает после ответа. Акторы дешевые, мы можем себе позволить такую модель выполнения.
При этом сессии мы храним
— либо в одном отдельном акторе — плохо, потому что, ботлнек.
— либо в отдельном акторе на каждую сессию, время жизни которого слабо связано с актором-исполнителем запроса. Акторы-сессии идентифицируются ключем сессии. Это метод хранения не-shared данных.
— либо, advanced level, в ets — in-memory-таблице, позволяющей доступ из нескольких процессов. Это для shared данных, вроде кэшей. В случае возникновения data race добавить дополнительные акторы, разруливающие запросы на запись.
Любой из перечисленных способов быстрее хождения за данными в другой ОС процесс.
Но в целом, несмотря на все грабли, писать удобнее и даже поприятнее.
Вот только удалить его забыли/забили.
Претензия к оригиналу — как обычно, про спорные аспекты поведения рантайма ни слова.
У WhatsApp, если мне не изменяет память, что-то вроде 11000 ядер на порядка 500 машин. Не помню точные числа, но о сравнимых по масштабу инсталляциях я больше не знаю.
Пару лет назад решили, а сейчас уже разговор идет о результатах. Эксперимент уже удался, советы не особо актуальны.
> простота и красота кода, которая в результате повышает продуктивность
Маркетинговый буллщит.
> Erlang совершенно точно ценят не за простоту,
> вспомним хотя бы парадигму функционального программирования.
Erlang не является функциональным ЯП, абсолютно точно. Тут есть пара комментариев, по которым заметна ошибочность и вредность этого подхода.
HOF, иммутабельность и pattern matching уже далеко распространились за пределы ФП.
И да, в посте отмечено, что Erlang — простой.
> склочности Erlang комьюнити
Нет никакой склочности. Вы приходите к людям, которые знают, что делают, и пытаетесь продать им что-то ненужное. Какой вы реакции ждали?
> хабр не получил какой то статьи
Замечательно. На хабре уже более чем достаточно go-фанбоев, хватит.
Позволю себе излишне обобщить — все присутствующие знают и Erlang, и Go, и прекрасно знают, что и когда применять. И то, что если нужно делать сетевые сервисы в масштабах Wargaming, выигрывает именно Erlang, при всех его недостатках, все тоже знают.
Упырьте мел, тут нет фанбоев, это же не пост про Go.
«в ets — in-memory-таблице, позволяющей доступ из нескольких процессов»
должно быть написано
«в ets — in-memory-таблице, позволяющей доступ из нескольких акторов». Первая формулировка, кажется, может ввести читателя в заблуждение.
Можно, но это уже не новичковый уровень. Я, честно говоря, никогда не испытывал нужды в Erlang distribution, поэтому знаю о нем очень мало, штука довольно неоднозначная. Скажем, WhatsApp используют его, но они и умеют его правильно готовить.
upd: давно не обновлял страницу
Это примерно такая же частая ошибка новичков, как упомянутый в статье дедлок gen_server:call.
Конечно, тут все сильно зависит от того, что мы пытались стартовать, зачем, как это обработается клиентом, если он есть, etc.
Вкратце, про рейс — если старт регистрируемого процесса происходит не в процессе-регистраторе, мы можем попасть в ситуацию, когда мы стартовали два инстанса регистрируемого процесса, один успешно регистрируется, попытка регистрации второго приводит к ошибке already_registered. Решается, насколько мне известно, только синхронным запуском процессов через регистратор, причем, я не уверен, является ли gproc:reg_or_locate/3 правильной реализацией.
А без процесса-регистратора все равно не выйдет, потому что без него получается классический race condition «регистрация после старта».
Ладно, может и выйдет, но я не могу так навскидку представить, как это реализовать.
Наиболее распространенная на сегодняшний день модель — у нас есть N воркеров в виде независимых процессов, по ним round robin распределяются запросы пользователей. Все вроде бы работает, но для хранения сессии между запросами нам нужно либо прикреплять пользователей к воркерам, что не очень удобно, либо иметь некое внешнее хранилище для всех сессий — собственно, redis или memcached.
В erlang подход несколько другой — мы запускаем один процесс ОС, в рамках которого на N ОС-тредах выполняется куча легковесных процессов(акторов), которые и выполняют пользовательские запросы. Причем, на каждый запрос создается новый актор, который умирает после ответа. Акторы дешевые, мы можем себе позволить такую модель выполнения.
При этом сессии мы храним
— либо в одном отдельном акторе — плохо, потому что, ботлнек.
— либо в отдельном акторе на каждую сессию, время жизни которого слабо связано с актором-исполнителем запроса. Акторы-сессии идентифицируются ключем сессии. Это метод хранения не-shared данных.
— либо, advanced level, в ets — in-memory-таблице, позволяющей доступ из нескольких процессов. Это для shared данных, вроде кэшей. В случае возникновения data race добавить дополнительные акторы, разруливающие запросы на запись.
Любой из перечисленных способов быстрее хождения за данными в другой ОС процесс.
Если не вдаваться в подробности — все.