为什么选择Erlang语言

手册/FAQ (524) 2015-12-02 15:11:40

       Erlang 是一个结构化的、动态的、函数式的编程语言。常见的一种说法是Erlang是面向并发的(Concurrent-Oriented),这主要指 Erlang在语言中定义了Erlang进程的概念和行为(本文中提到的“Erlang进程”都是指Erlang语言中定义的进程,以区分于大家熟悉的操作系统进程)。与操作系统的进程/线程相比,Erlang进程同样是并发执行的单位,但特别轻量级,它是在Erlang虚拟机内管理和调度的“绿进程”, 即用户态进程(如图2所示)。举个例子,在关闭了HiPE和SMP支持的Erlang虚拟机中,一个新创建的进程占用的内存仅为309个字 (Word,64位服务器上为8个字节)。其中233个字为堆空间(包含栈),创建和结束一个进程约耗时1~3微秒,而一个Erlang虚拟机中可以同时 支持几十

      说到Erlang语言,就必须提及OTP(Open Telecom Platform,开放电信平台)。OTP是用于开发分布式的、高容错性的Erlang应用程序的框架与平台。例如,一个Erlang节点连接并注册到 Erlang集群上,发现集群中的其他节点,并与它们进行RPC通信,这些都在OTP里的Kernel服务中实现。OTP和Erlang语言关系如此紧 密,以至于两者通常合称为Erlang/OTP,因此从严格的意义上来讲,应该说我们选择了Erlang/OTP来构造UMP系统。Erlang/OTP 很好地抽象了开发一个分布式的、高容错性的应用程序所需的要素,包括网络编程框架、序列化和反序列化、容错、热部署。

      为了支持并发,服务器 端多采用多进程/多线程模型,即每个进程/线程处理一个客户端连接。但受限于操作系统资源,每台服务器可以处理的并发连接数并不高,且由于进程/线程上下文切换开销,系统性能会受到影响。而开发高并发、高性能服务器一般采用事件驱动的状态机模型,底层采用非阻塞I/O(Linux中的epoll,BSD系 统中的kqueue,Java中的nio)或者异步I/O,或者采用异步的事件通知的I/O框架,例如C/C++下的ACE、boost::asio、 libevent,Java下的MINA等。在业务层则使用状态机来表示每个客户端连接,通过I/O事件、超时事件驱动状态机进行跳转,每个进程/线程可 处理成千上万个客户端连接。与多进程/多线程模型相比,虽然事件驱动的状态机模型并发量更大、性能更好,但把业务逻辑表达成状态机是一件困难的事情。相比 之下,多进程/多线程模型中的业务逻辑可以实现为顺序执行的代码,开发起来要简单得多。

      Erlang/OTP中的网络编程模型则结合了两者 的优点,每个Erlang进程处理一个客户端连接,业务逻辑是顺序执行的。Erlang进程是极轻量级的,可以认为每个Erlang进程是一个状态机,堆 和栈上的数据是这个状态机的状态。Erlang进程收到数据包或者其他进程发来的消息后执行处理例程,相当于状态机的跳转,因此也具有高并发和高性能的优 势。

      Erlang/OTP定义了“External Term Format”协议将Erlang数据结构与二进制字符串相互转化,并用C实现在Erlang虚拟机中,在进行跨节点通信时遵从这个协议。因此,开发者无须额外考虑序列化和反序列化问题。

      在容错方面,Erlang进程的数据空间是相互隔离的,没有共享内存,因此一个Erlang进程崩溃不会影响其他Erlang进程运行,更不会造成 Erlang虚拟机崩溃。OTP提供了监督树机制和heart模块,前者在监控到Erlang进程崩溃时进行故障恢复,后者在发现Erlang虚拟机失去 响应时重启程序。

      Erlang/OTP提供热部署方式,可以避免服务升级时造成不可用时间。此外,OTP还提供了一些在系统运行时观察系统状态的工具。例如lcnt工具,可以统计虚拟机内部的锁使用次数和冲突次数,指导系统的优化。

 

THE END