入手Erlang

2012-06-04 20:04

入手Erlang

by baiyuzhong

at 2012-06-04 12:04:15

original http://www.programmer.com.cn/11936/

似Erlang这般充满神秘感的语言寥寥无几。这门并发语言既可将难事化易,也可将易事变难。在健壮企业部署方面,它的虚拟机BEAM是唯一堪与Java虚拟机匹敌的对手。它调用起来十分高效,甚至效率以外的东西它都很少考虑。因此,它的语法也不像Ruby那样优雅和简洁。

Erlang其名,乍听之下很怪。但你若知道,它既是Ericsson Language的缩写,又恰是一位丹麦数学家的大名,你就不会再抱怨“这什么破名儿”了。作为电话网络分析的数学奠基人,Agner Karup Erlang可称得上是赫赫有名。

1986年,Joe Armstrong在爱立信公司(Ericsson)开发了Erlang语言的首个版本。随后的五年间,Erlang在他的精心雕琢下日渐完善。20世纪90年代整整十年间,Erlang的发展都不温不火、时断时续,但到了2000年之后,它却开始成为众人瞩目的焦点。两个广受欢迎的云数据库CouchDBSimpleDB,都是用Erlang开发出来的,此外,Erlang还是Facebook的聊天系统所采用的语言。正因为Erlang身怀可伸缩并发性和可靠性这两项拿手绝技,而其他语言在这两方面都力不从心,所以Erlang开始越来越多地成为人们谈论的话题。

为并发量身打造

Erlang是爱立信公司历经多年研究的产物,用来在电信领域中开发准实时(near-real-time且容错性较强的分布式应用。这类系统通常不可因维护而停止,因此软件开发费用极其高昂。20世纪80年代,爱立信对很多编程语言进行了研究,发现它们出于各种原因,均无法满足他们公司的需求。正是这些难以满足的需求,最终导致了一门全新语言的问世。

Erlang是一门函数式语言,可靠性方面的特性很多,可用于开发可靠性要求极高的系统。Erlang在替换模块时不必停止运行,这样就能边运行边维护电话交换机等设备。有些使用Erlang的系统已持续运行多年,从未因维护而中止过。可话说回来,要说到Erlang关键的功能,那还得是并发。

哪些方法最适用于并发?在这一点上,并发领域的专家们有时意见并不统一。其中常见的一个争议是:线程更好还是进程更好?一个进程由多个线程组成,进程有自己的资源,而线程虽有自己的执行路径,但在同一进程内,各线程是资源共享的。尽管实现各异,但一般来说,线程比进程更轻量级。

无线程

很多语言都采用线程实现并发,比如JavaC语言。线程占用资源较少,所以理论上说,使用线程可获得更优异的性能。线程的缺点,在于资源共享可能导致复杂而有缺陷的实现,而且这种资源共享必须用并发锁来管理,这也会产生性能瓶颈。为了在共享资源的两应用间分配控制权,线程机制需要借助信号量或是操作系统级别的锁。然而,Erlang另辟蹊径,尝试让进程也尽可能轻量级一些。

轻量级进程

Erlang奉行的哲学是轻量级进程,这使它摆脱了在共享资源和性能瓶颈的泥沼中艰难跋涉的困境。Erlang的发明者煞费苦心地简化了应用程序中多进程创建、管理和通信的过程。分布式消息传递成为基本的语言结构,因此锁机制不再必要,并发性能也大有长进。

Io一样,Erlang也将actor用在了并发当中,因此,消息传递就成为至关重要的概念。你可以在Erlang依稀辨认出Scala的消息传递语法,因为它们的消息传递语法非常相似。Scalaactor代表一个对象,由线程池创建和维护,而Erlangactor代表了一个轻量级进程。Erlangactor从队列中读取外部进入的消息,并用模式匹配决定其处理方式。

可靠性

Erlang虽然也有常规错误检测手段,但在容错应用中,需要处理的错误加起来远比传统应用要多,这是常规手段无法解决的。Erlang解决这一问题的秘诀是“就让它崩溃”。由于Erlang能轻易监测到崩溃进程,因此终止相关进程并启动新进程也就不在话下了。

此外,Erlang还能做到“热插拔”代码。也就是说,你不必中止代码运行,就可以替换应用程序的各个部分。相比于其他同类分布式应用,这项功能将带给你更简单的维护策略。Erlang将健壮的“就让它崩溃”错误处理策略、“热插拔”以及创建开销极小的轻量级进程等优点集于一身,因此应用程序一次就能运行好几年都不宕机。

Erlang有这么多并发方面的传奇特性,实在是令人欲罢不能。它有三个最基本的要素:消息传递、进程创建和进程监控。用它新创建的进程是轻量级的,因此不必担心其控制区域内的资源可能受限。Erlang不仅可以尽可能地消除代码中的副作用和可变性,而且还可以很轻松地监测崩溃进程。有了这些特性,说它人见人爱真是一点都不过分。

采访Erlang的发明者

Joe Armstrong博士是Erlang的发明者,也是《Erlang程序设计》一书的作者。我和这位来自瑞典斯德哥尔摩的Erlang语言首位实现者的访谈记录如下。

Bruce你为什么要开发Erlang

Armstrong博士:纯属巧合。我本来没打算发明一门新的编程语言。当时,我想找一种更好的方式来编写电信交换控制软件。我先试了试PrologProlog是一门绝妙的语言,但它无法完全满足我的需要,既然如此,我就开始瞎倒腾Prolog。我琢磨着:“如果改变一下Prolog的编程方式,那会怎样?”于是,我写了个Prolog的元解释器,给它加上了并行进程,还加上了错误处理机制,诸如此类。就这样,过了一段时间,我给这些新增加的变化起了个名字——Erlang,一门新语言就这么诞生了。之后,越来越多的人加入这个项目,这门语言也逐渐发展起来。我们想出了编译它的方法,加入了更多东西,获得了更多用户……

Bruce你最喜欢它哪一点呢?

Armstrong博士:我最喜欢它的错误处理、运行时代码升级机制,还有位级(bit-level)模式匹配。错误处理是这门语言最不为人所知的部分,也是与其他语言差别最大的部分。Erlang“非防御”编程和“就让它崩溃”这一套概念,既是它的独门绝学,也是它与传统方法截然相反之处。不过,这样做的确能编出简洁而漂亮的程序。

Bruce如果能让时光倒流,你最想改变哪项特性?(换言之,你也可以回答这样一个问题:Erlang最大的局限是什么?)

Armstrong博士:这问题很难,我可能会在不同时间给出不同答案。为这门语言添加一些移动特性应该不错,这样我们就能通过移动通信网络传送计算结果。我们可以用库代码来做这件事,但它并不被语言本身所支持。我现在想,如果追本溯源,把Prolog式的谓词逻辑加入Erlang,产生一种谓词逻辑和消息传递的全新组合,那想必会十分美妙。

还有不少小改动也是我想做的,比如说,加入散列映射、高阶模块,等等。

要是推倒重来,我可能会更多地把心思花在各项编程事务的协调上,比如说,如何运作有大量代码的大型编程项目——如何管理代码版本、如何搜索想要的东西、各种事物如何演化。当程序员编写了大量代码之后,他的任务就不再是编写新代码,而是准确找到现有代码,并把现有代码整合起来。因此,搜索和协调就变得日渐重要。如果把GITMercurial这类系统的思想吸收到Erlang之中,再给它加上类型系统,使它能在可控条件下理解代码是如何演化的,那我想应该会带来不错的效果。

Bruce在实际产品中,你见过的最特别的Erlang应用是什么?

Armstrong博士:嗯,其实我并不会太过惊讶,因为我早就知道它能达到何等高度。当我把Ubuntu版本升级到Karmic Koala时,我发现,它为了支持正在我机器上运行的CouchDB,而在后台悄悄启动了Erlang。这就好比Erlang在雷达的严密监控之下,偷偷溜进了数千万用户的计算机当中。

本文节选自《七周七语言:理解多种编程范型》一书,Bruce A. Tate著,戴玮,白明, 巨成译,由人民邮电出版社出版。