在现实世界中容错就是真金白银。程序员并不完美,需求往往也不完善。正如航空工程师处理有缺陷的钢材和铝材一样,为了有效处理有缺陷的代码和数据,我们需要能够容错的系统,以防系统在遭遇突发状况时土崩瓦解。
和许多其他编程语言一样,Erlang也具备异常处理机制来捕获特定代码段的错误,不过它还有一套独一无二的可以有效处理进程故障的进程链接系统,我们即将在此进行讨论。
1.进程链接如何工作
Erlang进程意外退出时,会产生一个退出信号。所有与濒死进程链接的进程都会收到这个信号。默认情况下,接收方会一并退出并将信号传播给与它链接的其他进程,直到所有直接或间接链接在一起的进程统统退出为止(参见图1-2)。这种级联行为可以使一组进程像单个应用一样退出,因此系统整体重启时你不必担心是否还有残存下来未能完全关闭的进程。
图1-2 崩溃进程发出的退出信号被传播到所有与之链接的进程,一般情况下它们会共同退出,以便完成对整个进程组的清理工作
前面我们曾提到过利用进程来清理复杂状态。其基本原理是:每个进程完整封装自己的全部状态,因此进程退出时系统的其余部分不会受损。如同单个进程一样,这一点对相互链接的进程组也同样适用。一个进程崩溃,与之协作的其他进程也一并退出,如此便可干净利落地抹掉之前建立的所有复杂状态,既节省了程序员的时间也减少了错误。
鼓励崩溃
当你还在绝望地纠结于如何挽回那些你可能根本无能为力的局面时,Erlang的哲学却是“鼓励崩溃”——精确记录下事发位置和经过后,把一切彻底抛下重新再来。这不太常见,但的确是一条强大的容错秘诀,而且按这个思路建立起来的系统无论多复杂度都可调试。
2.监督与退出信号捕捉
OTP实现容错的主要途径之一就是改写退出信号默认的传播行为。通过设置trap_exit进程标记,你可以令进程不再服从外来的退出信号,而是将之捕捉。这种情况下,进程接收到信号后,会先将其转为一条格式为{'EXIT', Pid, Reason}的消息,该消息描述了哪个进程出于什么原因而发生故障,然后这条消息会像普通消息一样被丢入信箱,捕捉到信号的进程就能分检并处理这类消息了。
这类会捕捉信号的进程有时被称为系统进程,它们执行的代码往往有别于普通的工作进程(即通常不捕捉信号的进程)。身为防范退出信号进一步传播的壁垒,系统进程阻断了与之链接的其他进程和外界之间的联系,因而可用于汇报故障乃至重启故障的子系统,正如图1-3所示。我们将这类进程称为监督者。
图1-3 监督者、工作者和信号:某工作进程的崩溃被级联传播至所有与之链接的其他进程,信号传播至监督者后,监督者将进程组重启。同一监督者辖区内的其他进程组则不受影响
停止并重启整个子系统的目的在于将系统恢复到一个已知的可正常工作的状态。这有点类似于重启电脑:通过重启你可以快刀斩乱麻地将电脑迅速恢复到可工作状态。但重启整台电脑的问题在于粒度太大。理想状况下,应该可以只重启系统的一部分,粒度越小越好。Erlang的进程链接与监督者共同提供了一种细粒度的“重启”机制。
不过,如果就到此为止,你还是得自己从头实现监督机制,这需要缜密的思考和丰富的经验,bug的清除和各种边界情况的处理也要花费大量的时间。幸运的是,OTP框架提供了你所需要的一切:既有运用监督机制来构建应用程序的一套方法,也有稳定的、经过实战考验的基础库。
OTP允许监督者按预设的方式和次序来启动进程。我们还可以告知监督者如何在单个进程故障时重启其他进程、一段时间内尝试重启多少次后放弃重启等。你所要做的就是提供一些参数和回调。
然而系统不应该只允许一层监督者工作者结构。在任何复杂系统中,你都可以用多层的监督树在多个层级重启子系统来解决各种意外问题。
3.进程的分层容错
通过分层可以将相关的子系统归于同一个监督者的辖区之内。更重要的是,这样做可以定义多个层级的基准工作状态,随时供你重置。在图1-4中,你可以看到两个分别受独立监督进程监督的工作进程组A和B。这两个组和它们的监督者共同形成了一个更大的进程组C,并由树中更高层的一个监督者负责。
图1-4 一个分层的监督者工作者系统。如果出于某种原因监督者A崩溃或退出,它辖区内所有尚还存活的进程都会被强制关闭,同时C会收到通知,于是进程树的左半边会被重启。监督者B则不受影响,除非C决定关闭整个系统
我们假设A组进程的任务是输出供B组使用的数据流。无须B组,A组也可正常工作。更具体一点,比方说A组在处理和编码多媒体数据,B组则予以展现。我们再假设A组处理的数据中有一小部分受损,且数据损坏的模式无法在开发应用时预测。
这种畸形数据会导致A组的进程工作异常。按照鼓励崩溃的哲学,进程不会尝试去解决问题而是直接崩溃;由于进程相互隔离,其他进程并不会受到错误输入的影响。监督者检测到进程崩溃后,会将A组重启以回退到预设的基准状态,从而使整个系统恢复到一个已知的基准点。美妙的是身为展现系统的B组完全不知晓也不关心这个过程。只要A组能为B组持续提供足够的优质数据,使后者能为用户展现质量过关的内容,你的系统就是成功的。
通过隔离系统中不相关的部分并将它们组织成监督树,你可以划分出多个子系统,每个都可独立地在几分之一秒内完成重启,这样一来,即便你的系统碰上不可预期的错误也可以稳健地运行。若A组无法正常重启,它的监督者最终会放弃重启并将问题上报至C组的监督者。在这种情况下,C组的监督者会一并关闭B组然后停工。想象一下若系统中同时运行着几百个C这样的子系统,这就相当于因数据错误而丢弃了一个多媒体连接,其他连接仍然照常工作。
然而,既然大家都跑在同一台机器上,就不得不共用一些东西:内存、硬盘驱动器、网络连接,乃至处理器和所有相关电路,还有一样最重要的,就是从同一个插座上接出来的那根电源线。如果这些东西中有一样发生故障或断开,不管怎么分层怎么做进程隔离都无法避免宕机。这就把我们带入了下一个主题,也就是分布式——能助你实现最高级别的容错并令你的解决方案伸缩自如的,正是Erlang的这个特性。
本文摘自——《Erlang/OTP并发编程实战》
分享到:
相关推荐
在IT行业中,Erlang因其在处理大规模并发连接和容错能力上的优秀表现,被广泛应用于通信、金融以及互联网等领域。 对于Java/C程序员来说,学习Erlang可以拓宽技术栈,提高解决复杂并发问题的能力。以下是一些关键...
Erlang是一种高级编程语言,专为构建并发、分布式、容错的系统设计。Erlang语言的编程规则和约定对于保证代码的可读性、可维护性、性能和稳定性至关重要。本文将对Erlang编程规则的中文翻译版本中的部分内容进行详细...
5. **简单错误处理**:Erlang的错误处理机制鼓励程序员以失败为先,使得编写健壮的代码变得更加容易。 **RPM包**: "erlang-22.3-1.el7.x86_64.rpm"是一个RPM(Red Hat Package Manager)包,是Linux发行版中常见的...
这两本电子书——《Erlang and OTP in Action》和《Erlang程序设计》——都是深入学习Erlang语言和OTP的宝贵资源。 《Erlang and OTP in Action》这本书主要分为三个部分。第一部分介绍Erlang语言的基础知识,包括...
- **第4章:函数式编程** —— 讲解函数式编程的基本原理及其在Erlang中的应用。 - **第5章:进程与并发** —— 详细介绍Erlang的进程模型和并发机制。 - **第6章:错误处理与容错** —— 讨论如何有效地处理错误和...
Erlang框架是一种基于Erlang编程语言的全功能Web框架,主要设计用于构建高度并发、可扩展且容错性强的Web应用。Erlang语言以其独特的并发模型和分布式计算能力而闻名,使得Erlang框架在处理大量并发连接和实时系统...
这个“erlang资源”包含两本PDF书籍——《Erlang并发编程》和《Erlang入门手册》,它们是深入理解和学习Erlang语言的关键资料。 《Erlang并发编程》这本书可能涵盖了以下知识点: 1. **并发模型**:Erlang的并发...
诊断以及调试生产环境中的Erlang 系统。在程序员学习新的语言和环境时,都需要一个摸索 阶段,也就是学会在社团的帮助下,脱离指南,解决实际问题。 本书假设读者精通基本的Erlang和OTP框架。在本书中,会对一些难以...
Erlang的第一个版本在1987年发布,而它的中间件和库的集合——Erlang/OTP(Open Telecom Platform),现在由爱立信的OTP产品部门支持和维护。 Erlang语言的主要特点包括: 1. 高并发处理能力:Erlang语言设计之初...
在学习过程中,了解Erlang的哲学——“失败是常态,恢复是例外”至关重要。Erlang鼓励程序员预期错误并优雅地处理它们,而不是避免错误。此外,Erlang的模块化设计和 OTP(Open Telecom Platform)框架为构建可扩展...
这本书深入浅出地介绍了Erlang在分布式系统、并发处理以及高可用性设计中的应用,同时结合 OTP 提供了强大的工具和库支持。通过阅读此书,读者可以掌握如何利用Erlang和OTP构建高效、容错的实时系统。 Erlang是一种...
### 程序员能力矩阵解析 #### 计算机科学 (Computer Science) - **2^n (Level 0):** 对计算机科学领域的基础知识几乎一无所知。这可能意味着程序员刚开始学习编程,尚未深入理解计算机科学的基本原理。 - **n^2 ...
Erlang OTP (Open Telephony Platform) 是一种高级并发编程语言和框架,主要由瑞典...通过下载并安装提供的"otp_win64_25.0.exe",用户可以开始探索Erlang OTP的世界,利用其强大的并发和容错能力来构建自己的项目。
Erlang是一种面向并发的、函数式编程语言,主要用于构建高度可扩展的、容错性强的分布式系统。在IT行业中,Erlang因其强大的实时性和处理大量并发连接的能力而被广泛应用于电信、互联网基础设施和实时系统。RabbitMQ...
不同层次的Erlang程序员都会发现本书是有价值的学习和参考资料。”, ——Steve Vinoski,《IEEE Internet Computing》专栏作家, 《Erlang编程指南》是对Erlang语言的深入介绍。Erlang是任何必须并发、容错和快速响应...
Erlang语言的设计理念源自于Ericsson公司为解决电信系统中的高可用性和容错性问题。其主要特点包括: 1. **并行计算**:Erlang的进程模型使得它能轻松处理大量并发操作,这对于网络游戏中的多玩家同步和实时交互至...
这种方式与现实世界中多任务并行的情况相吻合,使得Erlang成为构建并发应用程序的理想选择。书中详细阐述了如何编写这样的并发程序,并探讨了编写分布式应用程序的关键技巧,如如何设计能够容忍错误和故障恢复的系统...
Erlang以其强大的错误恢复能力和容错性著称,其虚拟机(BEAM)允许程序在不停止服务的情况下进行热更新。Erlang的进程模型使得它在处理大量并发连接时表现出色,这使得它成为构建高可用性系统的一个理想选择。 ...
此书可能包含如何设计容错架构、处理网络分区和数据一致性问题等内容。 4. **错误处理与容错**:Erlang的设计哲学是“失败快速,恢复快速”。这意味着系统应该预期到错误并准备好优雅地处理它们,而不是避免错误。...
Erlang是一种强大的编程语言,特别适合于构建高并发、分布式和容错性强的系统。由爱立信的CS-Lab开发,Erlang的设计目标是处理大规模并发活动,这在传统的操作系统上可能非常困难。它的核心特性使其在处理并发性、...