Where does Elixir/erlang fit into the microservices approach?

Lately I've been doing some experiments with docker compose in order to deploy multiple collaborating microservices. I can see the many benefits that microservices provide, and now that there is a good toolset for managing them, I think that it's not extremely hard to jump into the microservices wagon.

But, I have been experimenting with Elixir too, and I am quite fond of the benefits that provides by itself. Given that it encourages packing your code into multiple decoupled applications, and supports hot code upgrades, how would you mix docker with elixir (or erlang, for that matter)?

For example, if I want to use docker because it provides dev-prod parity, how does elixir fit in that? Given that docker containers are immutable, I lose the ability to do hot-code upgrades, right? What about blue/green deployments or canary releases?

I mean, I could just write microservices with Elixir and use them as if they were written in any other language, polyglotism is one of the benefits of microservices anyway, but then I'm not getting the full benefits of using the OTP platform, I guess that pure collaborative erlang applications are way more optimal that using intermediate queues to communicate between microservices written in different (or not) languages.

13312 次浏览

这是一个非常开放的问题,但我将试图说明为什么 Elixir/Erlang 可能是开发分布式系统的最佳平台(无论您是否使用微服务)。

首先,让我们从一些背景开始。Erlang VM 及其标准库是为构建分布式系统而预先设计的,这一点确实体现了出来。据我所知,它是为这个用例预先设计的生产环境中唯一广泛使用的运行时和 VM。

Applications

例如,你已经暗示了“应用程序”,在 Erlang/长生不老药中,代码被打包在应用程序中,这些应用程序包括:

  1. 启动和停止你的系统是一个启动所有应用程序的问题
  2. 提供统一的目录结构和配置 API (这不是 XML!).如果您已经使用并配置了 Open Telecom Platform (OTP)应用程序,那么您就知道如何使用任何其他应用程序
  3. 包含您的应用程序监视树,包含所有进程(我所说的进程是指“ VM 进程”,它们是轻量级的计算线程)及其状态

这个设计的影响是巨大的。这意味着 Elixir 开发人员在编写应用程序时有一个更明确的方法:

  1. 他们的代码是如何启动和停止的
  2. 什么是构成应用程序一部分的进程,因此什么是应用程序状态
  3. 当发生崩溃或出现问题时,这些过程将如何反应和受到影响

不仅如此,围绕这个抽象的工具非常棒。如果您已经安装了 Elixir,打开“ iex”并键入: :observer.start()。除了显示有关活动系统的信息和图表之外,还可以关闭随机进程,查看它们的内存使用情况、状态等。下面是在 Phoenix 应用程序中运行此命令的示例:

Observer running with a Phoenix application

这里的区别在于应用程序和进程为您提供了一个 抽象到对生产中的代码进行推理。许多语言主要为代码组织提供包、对象和模块,而在运行时系统上没有反射。如果您有一个 class 属性或者一个 singleton 对象: 您如何推断可以操作它的实体?如果存在内存泄漏或瓶颈,如何找到对此负责的实体?

如果你问任何一个运行分布式系统的人,他们想要的就是这种洞察力,而 Erlang/Elixir 就是这种洞察力的基石。

沟通

All of this is just the beginning really. When building a distributed system, you need to choose a communication protocol and the data serializer. A lot of people choose HTTP and JSON which, when you think about it, is a very verbose and expensive combination for performing what is really RPC calls.

使用 Erlang/Elixir,您已经有了一个通信协议和开箱即用的序列化机制。如果您想让两台机器相互通信,只需给它们命名,确保它们具有相同的秘密,就可以完成了。

Jamie 在 Erlang Factory 2015上谈到了这一点,以及他们如何利用这一点来构建一个游戏平台: https://www.youtube.com/watch?v=_i6n-eWiVn4

If you want to use HTTP and JSON, that is fine too and libraries like Plug and frameworks like Phoenix will guarantee you are productive here too.

微服务

到目前为止,我还没有谈到微服务。那是因为,到目前为止,它们并不重要。您已经在围绕隔离的非常小的进程设计系统和节点。如果你愿意,可以叫他们纳米服务!

不仅如此,它们还被打包到应用程序中,这些应用程序将它们分组为可以作为单元启动和停止的实体。如果您有应用程序 A、 B 和 C,然后希望将它们部署为[ A、 B ] + [ C ]或[ A ] + [ B ] + [ C ] ,那么由于它们的固有设计,这样做的麻烦很小。或者,更好的是,如果您想避免将微服务部署的复杂性添加到您的系统中,您可以将它们完全部署在同一个节点中。

最后,如果您使用 Erlang 分布式协议运行所有这些,那么您可以在不同的节点上运行它们,只要您通过 {:node@network, :name}而不是 :name引用它们,它们就能够到达其他节点。

我可以更进一步,但我希望我已经说服你在这一点:)