【问题标题】:Understanding Elixir了解长生不老药
【发布时间】:2019-10-07 22:24:15
【问题描述】:

像 SpringBoot 和 Play 这样的 Java 框架能否通过利用机器上的所有内核同时处理多个请求?如果他们能做到这一点,那么 Elixir 在并发方面解决了什么独特的问题?它只是一种不同的语言吗?或者计算范式本身有什么不同可以让我们使用 Elixir 降低服务器成本?

报告如下: https://www.techworld.com/apps-wearables/how-elixir-helped-bleacher-report-handle-8x-more-traffic-3653957/

【问题讨论】:

  • 这是一个需要大量讨论的问题,因此对于 StackOverflow 来说这不是一个好问题。投票结束。
  • Spring boot 具有 webflux 和 websocket 代理,可以同时高效地处理多个请求。剩下的就看VM了,所以这个问题可以转为“JVM还是BEAM哪个效率更高?”

标签: spring-boot playframework elixir


【解决方案1】:

主要有三个区别。

轻量级流程

Elixir 的进程不应与操作系统进程混淆。 Elixir 中的进程在内存和 CPU 方面非常轻量级(即使与许多其他编程语言中使用的线程相比)。正因为如此,同时运行数万甚至数十万个进程的情况并不少见。 ——https://elixir-lang.org/getting-started/processes.html

容错

Erlang 因此 Elixir 使用了 supervision tree 的概念,确保单个进程的崩溃不会对整个应用程序;更重要的是,Erlang 哲学明确将“让它崩溃”作为其座右铭。这基本上意味着您在某种程度上不应该关心错误处理。

主管有一个内置机制来限制在给定时间间隔内可能发生的重启次数。这是由两个参数 MaxR 和 MaxT 的值决定的。如果在最后 MaxT 秒内发生的重启次数超过 MaxR 次,则主管关闭它所监管的所有子节点并死亡。 ——http://erlang.org/documentation/doc-4.9.1/doc/design_principles/sup_princ.html

消息传递

Erlang 进程不是数据共享,而是完全隔离,唯一的交换机制是传递消息;这使得内存管理非常有效和高效。

每个进程都有自己的接收消息输入队列。收到的新消息放在队列的末尾。当进程执行接收时,队列中的第一条消息与接收中的第一个模式匹配。如果匹配,则从队列中删除消息并执行与模式对应的操作。 ——http://erlang.org/doc/getting_started/conc_prog.html#message-passing

【讨论】:

    【解决方案2】:

    问题

    在多核上处理多个请求的困难之一是您现在有多个程序部分同时运行并修改状态。因此,有了互斥锁,您现在必须担心函数是否是线程安全的,并管理锁和互斥锁的阻塞/等待/恢复。这意味着您现在有一堆潜在的瓶颈,这会增加成本并减少(甚至消除)您期望从并发中获得的收益。

    进入左侧舞台

    Erlang 和 Elixir 具有基于 'Actor Model' 的并发性。 Actor 接收消息,并且可以从这些消息中创建新消息、确定如何处理下一条消息、修改自己的内部状态或创建更多 Actor。归结为每个 Actor 都有自己的状态,因此您不再需要担心锁或互斥锁。这有助于减轻编写并发代码的精神负担,并且作为一种抽象可以更容易地推理并发。结果是更有效的并发代码更易于维护。 Actor 模型可以用任何语言实现,但它已融入 Elixir 和 Erlang。

    此外,Elixir 和 Erlang 是函数式语言。在函数式语言的副作用中,来自先前方法调用的挥之不去的状态通常是可以避免的。这意味着只要您不违反功能纯度,您就可以说一个方法每次都会返回相同的东西。这意味着 f(x) + f(x) == f(x)*2。这意味着您可以在更大程度上将事物并行化,而不必担心。在一个线程上运行 f(x) 和在另一个线程上运行 g(x) 如果它们在功能上是纯的,则不会导致竞争条件。因为它们都不会影响状态。

    【讨论】:

      【解决方案3】:

      我将尝试给出一个简短的答案: Erlang/Elixir 强制您使用actor编写异步、非阻塞代码。

      您可以将参与者视为“微”-微服务。 Actor 有自己的状态,它们不共享数据(实际上所有变量都是不可变的),因此需要在彼此之间传递异步消息。

      Erlang/Elixir 有自己的虚拟机,可以处理数十万个线程和其他优化(线程不是操作系统线程,而是虚拟/轻量级线程,即使所有变量都是不可变的,虚拟机也避免在内存中复制数据,仅在真正需要时复制数据)

      我不了解其他 Actor 系统的最新情况,因此我无法判断是否例如JVM 上的 Akka 将获得类似的性能。 Virtual Actor Systems 或许也能处理很多工作,Orleans 就是这样一个框架。 (虚拟actor系统可以比作Actor的依赖注入,当你需要它们时,它们会被创建,当它们不被使用时,它们会从内存中删除)https://github.com/dotnet/orleans

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-02-01
        • 1970-01-01
        • 2010-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多