为什么选择Erlang

首先,我想谈谈 Erlang 在 2010 年被 KAZOO 选中的一些较高层次原因。即使你不是技术人员,我希望你能在阅读本文中找到一些价值。

一些 Erlang 的历史

Erlang 于 1986 年在爱立信开发,并于 1998 年开源。它旨在改进爱立信内部电话应用程序的开发。

Erlang 可以分为三个主要部分:

  1. Erlang 语言 – 一种规则和语法相对较少的小语言(与其他现代语言相比)
  2. 开放电信平台 (OTP) – 中间件、库和工具的集合
  3. Erlang 虚拟机 (BEAM) – 执行已编译 Erlang 的指令(如果您熟悉Java的话,类似于 JVM)。

语言、OTP 的特性与运行 BEAM 相结合,提供了一个强大的平台,在该平台上构建需要容错性和面对错误时的弹性的系统。

一些 KAZOO/2600Hz 历史

了解现在 KAZOO 的主要途径源于Darren 和 Karl 运营电信基础设施的经验以及更广泛的社区经验。随着 2600Hz 就其电信基础设施咨询越来越多的公司,人们如何构建这些系统的模式和共同痛点出现了。KAZOO 旨在解决这些共性问题,同时还公开了允许运营商和经销商提供真正增值功能的功能。归根结底,大多数电信都是僵硬的、常规的和商品化的——连接两部电话或提供语音邮件不会赢得客户的心。

表面之下

客户甚至服务提供商的管理层可能不理解或不欣赏的是以下方面的所有复杂性和困难:

  • 编写优雅地处理错误的软件
  • 跨多个服务器扩展所述软件
  • 跨多个数据中心扩展所述服务器集群

单服务器软件

大多数软件(包括电信)都是为在单个服务器上运行而编写的。随着服务器处理负载的增加,软件的应对能力下降,最终达到硬件本身的极限。

想象一个发展中的小镇,只有一家杂货店,居民没有办法开车去其他城镇——杂货店的过道会挤满人,结账排队的等待时间会很可怕(商店只能容纳这么多的店员和收银员) .

当商店出现问题(例如,鸡蛋掉在地板上)时,需要更长的时间才能修复,并且不相关的客户将受到影响。商店没有优雅地处理错误。

Erlang 提供了一种方法来管理这种复杂性并使各个客户(流程)彼此隔离。现在一位顾客掉下的鸡蛋不会影响其他任何人!一个客户的大订单不必把所有其他客户都挡在他们身后;寄存器可以动态地打开和关闭以适应需求(当然仍然受商店的空间限制 – 我们在这里没有违反物理定律!)。

但是,单个服务器上的软件是存在单点故障的(SPOF)!任何数量的事件——意外的、预期的或恶意的——都可能使服务器无法访问。

添加服务器

在某个时刻,很明显需要一家新商店。传统方法是添加新服务器(杂货店)并将工作(客户)直接添加到其中一个或另一个(这通常是运行负载平衡器的服务器)。负载均衡器引入了新的复杂性,因为工作单元(客户)并不相同。

平衡工作

可供选择的选项是使用像循环这样的“哑”负载共享算法,或者创建一个必须与底层服务器通信的“智能”负载平衡器,以了解哪个服务器有能力接受更多工作。

循环和类似策略的最大缺点是负载分担不平衡(一家杂货店吸引了所有有需要的顾客并陷入困境,而另一家商店则获得了所有只是“仅仅需要鸡蛋”的顾客,而商店仍然大部分是空的)。

当然,使用“智能”选项,这些智能需要由某人构建,现在您有第三台服务器进行通信(具有分布式系统的所有讨厌的东西)。

协调工作

不是为跨服务器运行而设计的软件的另一个问题是它们彼此之间不协调。在杂货店的类比中,如果 1 号商店的屠夫知道顾客在 9:00 左右来取一块特定的肉,那么屠夫可以为该顾客准备好(预热缓存),从而加快,为客户提供更愉快的体验(电话连接速度可能更快)。如果由于某种原因客户偏离并去商店#2,与之前的访问相比,该服务将是次优的。

软件通常通过使用共享数据库(通常在单独的机器上)来解决这个问题。而你现在又有了单点孤战( SPOF)!如果无法访问数据库服务器,则服务器也将无法运行。所以现在你需要第二个数据库服务器和一些冗余。

Erlang 使服务器间通信更容易

Erlang 为程序员提供了工具,使与其他服务器的进程(运行 BEAM 的副本)的对话和与本地 BEAM 及其进程的对话一样简单和透明。如果服务器无法访问,则可以设置现有服务器以接收这些事件并做出相应反应。应用在上个例子中,两家商店的屠夫都可以就客户的需求进行沟通,并且无论客户选择哪家商店,他们都做好了准备。

添加数据中心

既然软件有一个共享数据库并且已经解决了 SPOF,那么软件需要考虑通过更广域网 (WAN) 进行通信——这通常是公共互联网。看,开发人员对计算机如何相互通信做出假设——大​​多数人只是假设来自一台计算机的数据包将以快速有序的方式到达目的地。然后根据这些错误的假设编写软件。虽然软件在单个数据中心运行(通常使用非常好的网络电缆和设备),但这些假设似乎成立。

但即使是数据中心也可能无法访问。公用事业公司意外切断了光纤电缆,飓风淹没了数据中心,带宽提供商出现了中断——这些事件的发生比大多数人想象的要多!然后,软件以意想不到的方式中断,找出原因成为一场噩梦。

实际问题

既然软件必须通过不太可靠的网络(数据中心间、公共互联网)和收费的电路进行通信(通常网络内通信是免费的或非常廉价的),技术上的新问题(增加的延迟、带宽饱和、丢包/重传)和业务(更高的带宽成本、数据中心扩建、新数据中心的本地技术?)成为新的现实。

例如,可以对本地网络上的服务器进行编程,以定期同步它们的状态(它们各自的世界),以保持基本一致的观点。根据系统的不同,这可能会导致使用许多额外的兆字节、千兆字节甚至 TB 的带宽,只是为了同步!(这甚至没有计算用于处理实际工作的带宽)。该数据不会立即传输,也不会免费传输(Amazon EC2 的起价为 0.09 美元/GB)。想象一下,由于服务器占用带宽来同步它们的状态,电话呼叫被延迟或现有呼叫的音频断断续续!

技术问题

有大量的计算机科学致力于分布式计算以及不可靠通信带来的所有痛点。遗憾的是,大多数程序员不太可能处理过这些类型的系统,或者没有适当的工具和基础设施来构建处理这些分布式计算问题的系统。

Erlang 本身也不是灵丹妙药。默认的通信机制在不可靠的网络上效果不佳。然而,一些项目正在解决这一差距,包括LaspPartisanRiak 流程组等。也可以使用其他技术(如Kazoo 所做的RabbitMQ)来帮助解决这个问题。

要将这些基础设施组件与不是为其设计的软件一起使用,需要大量投资来重写软件,或者更常见的是,软件将尝试在软件本身内模拟功能(而且通常很差)。

大多数电信基础设施的问题

简而言之,目前的软件不是为跨地理分布的网络运行而设计的,也没有考虑通过不可靠的网络进行通信所固有的错误和问题。这些功能通常是在来自管理层的压力和分布式系统开发经验不足的团队的压力下设计的,因此通常实施不善,并且充斥着错误和效率低下。

然而,无论好坏,软件在很大程度上是因为底层基础设施是健壮的——这会滋生一种虚假的安全感,营销团队开始用“可靠性”和“冗余”来描述他们公司的产品。

然而,当事情确实出错时(正如墨菲定律所示,它们总是这样),代价是要付出很多倍的。“一点点的预防胜过无数的治疗”。

那么为什么选择 Erlang?

鉴于事情确实出错了,即使是最聪明的团队也无法预料到所有错误,所以工作是从最低级别开始优雅地处理已知和未知错误(容错)是理所当然的。

Erlang 有一个与工作单元相关的“任其崩溃(Let it crash)”的理念 – 如果数据错误,外部资源不可用,无论如何,让工作者进程崩溃(停止它)并让监督进程处理崩溃。这可能是重新启动一个新的工作者进程,将错误上升并响应,记录崩溃并继续,或者任何数量的所需策略。Erlang 和 OTP 的价值在于将这些问题放在首位和中心位置,并为程序员提供了有序处理它们的工具。

因为启动和停止工作进程是微不足道的,所以代码的架构受益于将“工作”与工作的“管理”和“监督”分开。结果,代码变得更小更简洁(在 Erlang 中,人们会说“快乐的编程”),这使得推理更容易,测试更容易,并且通常应该更快地生成更好的代码。

放到一起

Erlang 提供了用于构建容错、弹性系统的语言 (Erlang)、框架 (OTP) 和运行时 (BEAM)。拥抱“Let it crash”的理念产生的代码可以更优雅地处理错误,允许系统作为一个整体在出现这些错误时保持稳定。

在此基础上,构建了高可用性、容错系统。

在以后的文章中,我将更深入地探讨 KAZOO 在 Erlang 的基础上做出的一些架构决策,以及这些决策如何影响 KAZOO 集群在所有级别的错误面前运行的能力,即使各个数据中心运行的代码因飓风洪水而消失。

Related Posts

2021 年你需要知道的关于 Erlang 的一切

今天,我们将看一个相当古老且有些古怪的东西。 你们大多数人可能没有注意到的语言。 虽然 Erlang 不像某些现代编程语言那样流行,但它安静地运行着 WhatsApp 和微信等每天为大量用户提供服务的应用程序。 在这篇文章中,我将告诉你关于这门语言的更多事情、它的历史,以及你是否应该考虑自己学习它。 ## 什么是 Erlang,它在哪里使用? Erl

Read More

Erlang JIT中基于类型的优化

这篇文章探讨了 Erlang/OTP 25 中基于类型的新优化,其中编译器将类型信息嵌入到 BEAM 文件中,以帮助JIT(即时编译器)生成更好的代码。 ## 两全其美 OTP 22 中引入的基于SSA的编译器处理步骤进行了复杂的类型分析,允许进行更多优化和更好的生成代码。然而,Erlang 编译器可以做什么样的优化是有限制的,因为 BEAM 文件必须

Read More

Erlang JIT之路

自从Erlang 存在,就一直有让它更快的需求和野心。这篇博文是一堂历史课,概述了主要的 Erlang 实现以及如何尝试提高 Erlang 的性能。 ## Prolog 解释器 Erlang 的第一个版本是在 1986 年在 Prolog 中实现的。那个版本的 Erlang 对于创建真正的应用程序来说太慢了,但它对于找出Erlang语言的哪些功能有用,哪

Read More