Это очень открытый вопрос, но я попытаюсь проиллюстрировать, почему Elixir / Erlang может быть лучшей платформой для разработки распределенных систем (независимо от того, работаете ли вы с микросервисами).
Во-первых, давайте начнем с некоторой предыстории. Виртуальная машина Erlang и ее стандартная библиотека были разработаны заранее для построения распределенных систем, и это действительно заметно. Насколько мне известно, это единственная среда выполнения и виртуальная машина, широко используемая в производственной среде, разработанная заранее для этого варианта использования.
Приложения
Например, вы уже намекнули на «приложения». В Erlang / Elixir код упакован внутри приложений, которые:
- запускаются и останавливаются как единое целое. Запуск и остановка вашей системы - это вопрос запуска всех приложений в ней.
- предоставить единую структуру каталогов и конфигурационный API (который не является XML!). Если вы уже работали и настроили одноразовое приложение, вы знаете, как работать с любым другим.
- содержит ваше дерево наблюдения за приложением со всеми процессами (под процессом я имею в виду «процессы виртуальной машины», которые являются легковесными потоками вычислений) и их состояние
Влияние этого дизайна огромно. Это означает, что разработчики Elixir при написании приложений более четко подходят к:
- как их код запускается и останавливается
- какие процессы составляют часть приложения и, следовательно, каково состояние приложения
- как этот процесс отреагирует и повлияет на него в случае сбоев или когда что-то пойдет не так
Мало того, инструменты вокруг этой абстракции великолепны. Если у вас есть Эликсир установлен, откройте «Iex» и введите: :observer.start()
. Помимо отображения информации и графиков о вашей действующей системе, вы можете убивать случайные процессы, видеть их использование памяти, состояние и многое другое. Вот пример запуска этого в приложении Phoenix:
Разница здесь в том, что приложения и процессы дают вам абстракцию для размышлений о вашем коде в производственной среде . Многие языки предоставляют пакеты, объекты и модули в основном для организации кода без отражения в системе времени выполнения. Если у вас есть атрибут класса или одноэлементный объект: как вы можете рассуждать о сущностях, которые могут им манипулировать? Если у вас есть утечка памяти или узкое место, как вы можете найти ответственный за это объект?
Если вы спросите кого-нибудь, кто работает в распределенной системе, то это именно то, что им нужно, и с 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], у вас будет очень мало проблем с этим из-за к присущему им дизайну. Или, что еще лучше, если вы не хотите заранее усложнять развертывание микросервисов в своей системе, вы можете просто развернуть их целиком на одном узле.
И, в конце концов, если вы работаете все это с помощью Erlang распределенного протокола, вы можете запустить их в различных узлах и они будут в состоянии достигнуть другой до тех пор , как вы обратитесь к ним {:node@network, :name}
вместо :name
.
Я мог бы пойти дальше, но надеюсь, что убедил вас на этом этапе. :)