Где Elixir/erlang подходят к подходу к микросервисам?

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

Но я тоже экспериментировал с Elixir, и я очень увлекаюсь преимуществами, которые дает сам. Учитывая, что он поощряет упаковку вашего кода во множество развязанных приложений и поддерживает обновление горячего кода, как бы вы смешивали докер с elixir (или erlang, если на то пошло)?

Например, если я хочу использовать докеры, потому что он обеспечивает dev-prod-четность, как это делает эликсир? Учитывая, что контейнеры-докеры неизменяемы, я теряю возможность делать обновления с помощью "горячего" кода, не так ли? Что можно сказать о синих/зеленых вариантах развертывания или канарейках?

Я имею в виду, я мог просто написать микросервисы с Elixir и использовать их так, как если бы они были написаны на любом другом языке, полиглотизм является одним из преимуществ микросервисов в любом случае, но тогда я не получаю все преимущества использования OTP платформе, я думаю, что чистые совлокальные приложения erlang более оптимальны, используя промежуточные очереди для связи между микросервисами, написанными на разных (или не) языках.

Ответ 1

Это очень открытый вопрос, но я попытаюсь проиллюстрировать, почему Elixir/Erlang может быть лучшей платформой для разработки распределенных систем (независимо от того, работаете ли вы с микросервисами).

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

Приложения

Например, вы уже намекнули на "приложения". В Erlang/Elixir код упаковывается внутри приложений, которые:

  • запускаются и останавливаются как единица. Запуск и остановка вашей системы - это запуск всех приложений.
  • предоставляют единую структуру каталогов и API-интерфейс конфигурации (который не является XML!). Если вы уже работали с и настраивали приложение OTP, вы знаете, как работать с любым другим.
  • содержит дерево контроля вашего приложения со всеми процессами (по процессу я называю "процессы VM", которые являются легкими потоками вычислений) и их состояние

Эффект этого дизайна огромен. Это означает, что разработчики Elixir при написании приложений имеют более четкий подход к:

  • как их код запущен и остановлен
  • каковы процессы, входящие в состав приложения, и, следовательно, что такое состояние приложения.
  • как этот процесс будет реагировать и быть затронутым в случае сбоев или когда что-то пойдет не так.

Не только то, что инструмент вокруг этой абстракции велик. Если у вас установлен Elixir, откройте "iex" и введите: :observer.start(). Помимо отображения информации и графиков о вашей живой системе, вы можете убить случайные процессы, посмотреть их использование памяти, состояние и многое другое. Вот пример запуска этого приложения Phoenix:

Observer running with a Phoenix application

Разница здесь в том, что приложения и процессы дают вам абстракцию о вашем коде в производстве. Многие языки предоставляют пакеты, объекты и модули в основном для организации кода без отражения в системе времени исполнения. Если у вас есть атрибут класса или одноэлементный объект: как вы можете рассуждать о сущности, которые могут манипулировать им? Если у вас есть утечка памяти или узкое место, как вы можете найти ответственную за нее организацию?

Если вы спросите кого-нибудь, кто работает с распределенной системой, что вид прозрения, который они хотят, и с Erlang/Elixir вы имеете это как строительный блок.

Связь

Все это только начало. При создании распределенной системы вам необходимо выбрать протокол связи и сериализатор данных. Многие люди выбирают HTTP и JSON, которые, когда вы думаете об этом, являются очень многословной и дорогостоящей комбинацией для выполнения действительно вызовов RPC.

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

Джейми рассказал об этом в Erlang Factory 2015 и о том, как они могли использовать это для создания игровой платформы: https://www.youtube.com/watch?v=_i6n-eWiVn4

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

Microservices

До сих пор я не говорил о микросервисах. Это потому, что до сих пор они не имеют большого значения. Вы уже разрабатываете свою систему и узлы вокруг очень маленьких процессов, которые изолированы. Назовите их наносервисами, если хотите!

Кроме того, они также упаковываются в приложения, которые группируют их как объекты, которые можно запускать и останавливать как единицу. Если у вас есть приложения A, B и C, а затем вы хотите развернуть их как [A, B] + [C] или [A] + [B] + [C], у вас будет очень мало проблем при этом к их неотъемлемому дизайну. Или, что еще лучше, если вы хотите избежать сложностей развертывания микросервисов в вашей системе, вы можете просто полностью их развернуть в одном и том же node.

И в конце дня, если вы используете все это, используя распределенный протокол Erlang, вы можете запускать их в разных узлах, и они смогут достичь других, пока вы ссылаетесь на них на {:[email protected], :name} вместо :name.

Я мог пойти дальше, но я надеюсь, что убедился в этом.:)