编写分布式的Erlang程序:陷阱和对策
分布式系统中的错误处理与异常处理(二)

分布式系统中的错误处理与异常处理引言:随着信息科技的迅速发展,分布式系统已经成为了现代计算机网络的核心组成部分。
然而,由于分布式系统的复杂性和规模,错误和异常问题也变得不可避免。
本文将探讨分布式系统中的错误处理与异常处理方法,以及如何提高系统的鲁棒性。
一、错误处理1. 错误的类型和原因:在分布式系统中,错误可以分为硬件错误和软件错误两大类。
硬件错误可能是由于服务器故障、网络中断等引起的,而软件错误则通常是由于程序设计错误、数据错误或者资源不足等导致的。
2. 错误的检测和定位:为了有效地处理错误,分布式系统需要具备错误的检测和定位能力。
其中,错误的检测可以通过使用监控工具和日志记录来实现,而错误的定位则需要通过分析日志和调试信息来确定错误发生的位置和原因。
3. 错误的恢复和重试:一旦错误被检测到并定位,分布式系统需要采取措施进行错误的恢复和重试。
其中,错误的恢复可以是自动的,例如通过备份服务器接管故障服务器的任务;或者是需要手动干预的,例如重新启动软件或重置硬件。
而错误的重试则需要根据具体情况进行调整,例如重新发送未成功的网络请求,直至成功为止。
二、异常处理1. 异常的类型和处理方式:异常是指在程序运行过程中遇到的非正常情况,包括但不限于输入错误、网络超时、资源不足等。
分布式系统中的异常处理需要建立多层次的异常处理机制,包括异常检测、异常传播、异常处理和异常恢复等。
2. 异常的检测和传播:分布式系统可以使用异常检测技术来检测异常的发生,例如监控网络连接状态和资源使用情况。
一旦异常被检测到,分布式系统需要将异常信息传播给相应的处理单元,例如通过消息队列、日志记录等方式。
3. 异常的处理和恢复:异常的处理包括异常的分类和处理策略的制定。
分布式系统可以根据异常的不同类型,采取针对性的处理方法,例如重新发送网络请求、自动切换到备用服务器等。
而异常的恢复则需要考虑数据的一致性和完整性,例如通过日志回滚、数据备份等手段进行恢复。
Erlang编程基础

Erlang编程基础Erlang是一种广泛用于并行和分布式应用程序的编程语言。
它是由瑞典电信公司Ericsson在20世纪80年代末到90年代初开发的,旨在解决电信系统在高度并发的情况下的通信和容错问题。
在过去的几十年里,Erlang 已经成为了编写高可靠、高并发的系统的首选语言之一。
Erlang的语法类似于Prolog,但也有类似于C语言的结构,并且支持面向对象的编程风格。
最重要的是,Erlang具有非常独特的并发模型,可以轻松地编写响应快速的服务器和分布式应用程序。
下面我们将介绍Erlang编程的基础知识。
1. 变量与类型在Erlang中,变量是以小写字母开头的单词或下划线组成的标识符,例如:```X = 1.Y = \"Hello, world!\".```Erlang中的主要数据类型包括整数、浮点数、布尔值、字符串和列表。
整数和浮点数的语法与C语言类似。
布尔值只有两个值:true和false。
字符串使用双引号括起来,例如:\"Hello, world!\"。
列表是相同或不同类型元素的列表,例如:[1, 2, 3]和[\"Alice\", \"Bob\", \"Charlie\"]。
2. 函数和模块Erlang是一种函数式编程语言,函数是Erlang编程的核心。
函数包括一个名称、参数列表和函数体,例如:```add(A, B) ->A + B.```这个函数将两个整数相加并返回其和。
函数定义以箭头符号(->)结束。
在Erlang中,函数通常分组到称为模块的文件中。
一个模块包含一组相关的函数和常量。
使用-module指令定义模块的名称,以及-export指令指定模块中可供其他模块使用的函数。
例如,以下是一个名为math的模块,定义了一个名为add的函数:```-module(math).-export([add\/2]).add(A, B) ->A + B.```要在其他Erlang代码中使用此模块中的函数,可加载该模块并调用函数:```-module(client).-compile(export_all).start() ->math:add(1, 2).```在这个例子中,我们定义了一个名为start的函数,加载了math模块,并调用了它的add函数。
编程中的个常见问题及解决方法

编程中的个常见问题及解决方法编程中的常见问题及解决方法在编程过程中,经常会遇到各种各样的问题。
这些问题可能会导致程序运行出错、效率低下或者功能无法实现。
本文将介绍一些编程中常见的问题,并提供相应的解决方法。
一、编译错误编译错误是编程过程中常见的问题之一。
当我们编写的代码存在语法错误或者逻辑错误时,编译器会提示错误信息,导致程序无法正常编译通过。
为了解决这类问题,我们可以采取以下几种方法:1. 仔细阅读错误信息:编译器会给出详细的错误信息,包括错误类型、错误位置等。
通过仔细阅读错误信息,我们可以找到问题所在,并进行相应的修改。
2. 逐行调试:通过添加调试语句或者使用调试工具,我们可以逐行地检查程序的执行过程,找出错误的位置和原因。
3. 参考文档和资料:在解决编译错误时,我们可以参考编程语言的文档和相关资料,查找解决方法或者类似问题的解决方案。
二、运行时错误运行时错误是指在程序运行过程中出现的错误,常见的有空指针异常、数组越界等。
为了解决这类问题,我们可以采取以下几种方法:1. 异常处理:在代码中使用异常处理机制,捕获并处理可能出现的运行时异常。
通过合理的异常处理,可以避免程序异常终止。
2. 输入合法性判断:在接收用户输入或者外部数据时,需要对其进行合法性判断。
例如,可以使用条件语句或者正则表达式对输入数据进行校验,防止出现运行时错误。
3. 调试工具:使用调试工具可以帮助我们定位运行时错误的位置和原因。
通过调试工具的断点调试功能,我们可以逐步跟踪程序的执行过程,找出错误所在的位置。
三、性能优化在编写大规模程序或者处理大数据量时,程序的性能成为一个重要的考虑因素。
为了提高程序的性能,我们可以采取以下几种方法:1. 程序优化:对代码进行优化,例如通过使用合适的数据结构、算法和编程技巧等,减少程序的时间和空间复杂度。
2. 并行计算:对于需要处理大量数据的任务,可以采用并行计算的方式,将任务分解为多个子任务,并通过多线程、分布式计算等方式进行并发处理,提高程序的运行效率。
Erlang并发编程技术解析

Erlang并发编程技术解析Erlang是一种高度并发的编程语言,被广泛应用于处理实时、分布式系统中。
在本文中,我们将深入探讨Erlang并发编程的技术,包括其基本原理、并发模型、进程通信、并发调试等方面的内容。
一、Erlang并发编程的基本原理Erlang的并发编程是建立在其独特的Actor模型基础上的。
在Erlang中,每个并发单位都是一个轻量级的进程,可以独立运行,接收消息,以及发送消息给其他进程。
这种基于消息传递的并发模型使得开发者可以编写出高度可靠、可扩展的并发程序。
二、并发模型Erlang采用了线程级并发模型,即每个Erlang进程都是一个轻量级的线程,共享同一个虚拟机。
Erlang的并发模型允许开发者创建成千上万个进程,并能高效地管理和调度这些进程。
这种模型使得开发者能够充分利用多核处理器的优势,实现真正意义上的并行计算。
三、进程通信在Erlang中,进程之间通过消息进行通信。
Erlang提供了一套强大的消息传递机制,使得进程间通信变得简单易用。
开发者可以通过发送消息和接收消息的方式来实现进程之间的通信。
此外,Erlang还提供了一些高级的通信机制,如共享内存、原子操作等,以满足不同场景下的并发需求。
四、并发调试Erlang提供了一些工具和技术来帮助开发者调试并发程序。
例如,开发者可以使用Erlang自带的调试器对程序进行分析和调试;还可以使用监视器来监控进程的运行状态;此外,Erlang还提供了一些函数和宏,用于处理并发编程中的常见问题,如死锁、竞争条件等。
五、并发编程的最佳实践在进行Erlang并发编程时,有一些最佳实践可以帮助开发者提高代码的可读性和维护性。
首先,设计良好的进程层次结构能够使得代码更加清晰,并提高代码的可扩展性。
其次,避免进程之间的紧耦合,采用松散耦合的设计能够减少错误和提高代码的可测试性。
此外,使用适当的异常处理机制能够提高程序的鲁棒性。
六、Erlang在实际应用中的案例Erlang的并发编程技术在实际应用中得到了广泛应用。
Erlang初学Erlang的一些特点和个人理解总结电脑资料

Erlang初学:Erlang的一些特点和个人理解总结 -电脑资料这篇文章主要介绍了Erlang初学:Erlang的一些特点和个人理解总结,本文总结了函数式编程、一切都是常量、轻量进程、进程端口映射及典型缺点等内容,需要的朋友可以参考下我对 Erlang 编程理念的理解:以分布式架构师的角度写代码,Erlang初学:Erlang的一些特点和个人理解总结函数式编程Erlang 里面的函数是数学里面的函数:必须有返回值。
只要是函数必然有返回值,函数是一个过程,以英文的句号为函数结束符。
函数结束之前的表达式就是该函数的返回值。
所以这也是在 Erlang 里面的函数不会看到任何 return 语句的原因。
C++ 等其他语言的函数和函数之前可以通过共享变量来实现消息传递。
Erlang 里面的函数不可以,消息的传递通过函数的传入和传出。
也只是为什么 Erlang 号称天生之处并行处理的原因,因为他们不共享变量,也就不需要加锁。
很多人听到函数式编程都会觉得高大上或者晦涩难懂。
因为函数是编程没有for 循环语句,但是在我看来,关键在于会使用【列表推倒】和【尾递归】来进行循环遍历。
说到函数式编程就会拿快速排序说事,下面这个示例是 Erlang 版本的快速排序:代码如下:-module(sort).-export([qsort/1]).qsort([]) -> [];qsort([Pivot | T]) ->qsort([X || X <- T, X < Pivot]++ [Pivot] ++qsort([X || X <- T, X >= Pivot]).非常简洁,[Pivot | T] 就是拿列表的第一个元素当快排中的 Pivot 。
代码如下:[X || X <- T, X < Pivot]上式就是【列表推导】,含义就是找出列表 T 中所有元素小于 Pivot 中的元素组成一个新的列表。
erlang的分布式

erlang的分布式
Erlang 分布式是一种基于 Erlang 语言和 OTP(开放电信平台)框架的分布式计算模型。
它允许开发人员构建可扩展、高可用性的分布式系统,通过在多个节点上运行并相互通信的 Erlang 进程来实现。
Erlang 是一种函数式编程语言,最初由爱立信公司开发用于构建可靠的、高并发的通信系统。
它具有轻量级进程、消息传递和模式匹配等特性,使得开发人员能够轻松地构建并发和分布式应用。
Erlang 分布式的优势包括:
- 可扩展性:分布式 Erlang 允许将应用程序分布在多个节点上,从而实现水平扩展。
开发人员可以根据需求增加或减少节点数量,以适应不同的负载。
- 高可用性:Erlang 的轻量级进程模型和消息传递机制使得构建高可用性系统变得更加容易。
总的来说,Erlang 分布式是一种强大的工具,它提供了可靠的分布式计算能力,使得开发人员能够构建可扩展、高可用性的应用程序。
如何解决分布式数据库的数据冲突与重复问题(系列十)

分布式数据库是当今计算机领域的重要组成部分,它能够帮助我们在多个节点之间共享和存储数据。
然而,由于数据的分散存储和节点之间的通信延迟等原因,分布式数据库面临着数据冲突和重复的问题。
本文将探讨如何解决这些问题,提供一些有效的方法和策略。
第一,合理设计数据模型。
在构建分布式数据库时,合理的数据模型设计是解决数据冲突和重复问题的关键。
首先,需要对数据进行合理的分片和分配,使得不同的数据片段存储在不同的节点上,减少数据访问冲突的概率。
其次,需要考虑数据的一致性和完整性,避免因数据冲突和重复导致的数据一致性问题。
第二,实现数据同步和一致性机制。
分布式数据库中的数据冲突和重复问题主要源于多节点之间数据的异步复制和更新。
为了解决这些问题,可以采用数据同步和一致性机制。
一种常用的方法是使用主从架构,通过主节点负责处理数据的写入和更新操作,从节点负责数据的复制和同步。
这样能够保证数据的一致性,减少数据冲突和重复的概率。
第三,引入分布式事务机制。
分布式数据库中的事务处理是非常重要的,它能够保证数据的一致性和完整性。
分布式事务机制可以解决数据冲突和重复问题的关键。
在进行分布式事务处理时,需要确保每个节点上的事务操作都是幂等的,并且能够正常回滚和恢复。
同时,需要合理设计事务的隔离级别,减少数据访问冲突和数据重复的概率。
第四,使用分布式锁机制。
分布式锁是解决分布式系统中数据冲突和重复问题的有效工具。
通过使用分布式锁,可以对共享数据进行互斥访问,避免多个节点同时进行读写操作,从而减少数据冲突和重复的概率。
此外,还可以使用分布式事务锁和乐观锁等技术,提高数据的并发性和一致性。
第五,监控和管理系统。
在分布式数据库中,及时监控和管理系统是解决数据冲突和重复问题的重要手段。
通过实时监控系统的运行状态和节点之间的数据传输情况,可以及时发现和解决数据冲突和重复的问题。
同时,还需要建立完善的数据备份和恢复机制,确保数据的安全和可靠性。
综上所述,解决分布式数据库的数据冲突和重复问题需要从多个方面着手。
分布式系统中的安全问题与挑战

分布式系统中的安全问题与挑战一、引言随着计算机技术的持续发展,分布式系统已经成为了相当流行的系统架构。
它不仅可以提高计算能力和系统可用性,还能为企业带来巨大的商业价值。
然而,分布式系统也带来了许多强制性的安全挑战。
在分布式系统中,安全问题成为了一大关注的焦点。
二、分布式系统中的安全问题分布式系统由多个组件、节点和服务组成,这也就为安全问题提供了更多的入口和机会。
以下这些是常见的安全问题:1. 访问控制和权限管理在分布式系统中,访问控制和权限管理是非常关键的一环,要保证应用只能被授权的用户或服务访问。
如果这些措施不完善或者存在漏洞,那么数据就有可能会遭到泄露或攻击。
2. 保护数据和通信在分布式系统中,通信是最基本的操作,但是这也为攻击者提供了机会,其可能截获或篡改数据包。
因此,必须采用加密和安全通信协议来保护通信和数据的安全。
3. 确保数据的一致性在分布式系统中,数据会同时存储在多个地方,因此可能存在数据不一致的情况。
因此,需要一些机制来确保数据的一致性,如数据同步。
4. 避免逆向工程和篡改大部分分布式系统软件的代码是公开的,因此攻击者可能通过分析代码的方法来找到漏洞。
为了尽可能地避免这种情况,软件应该采用各种技术来保护代码,如反编译和代码混淆。
5. 恶意攻击分布式系统面临的大多数威胁都是恶意攻击。
在这些攻击中,攻击者可能会打破系统的访问控制并获取数据或控制系统。
这种攻击可能还会导致拒绝服务、窃取密码等问题。
三、分布式系统中的安全挑战1. 网络隔离:分布式系统中的不同节点通常是通过网络连接在一起的。
通常情况下,可以采用网络隔离来确保分布式系统中的安全。
网络隔离涉及许多方面,其中包括物理隔离、虚拟隔离、逻辑隔离等。
2. 多节点管理:在分布式系统中,有多个节点需要统一管理。
因此,需要一种方法来确保各个节点的安全和管理。
这通常可以通过中央控制器的方式来实现,但也可能给攻击者留下漏洞。
效,导致数据的不一致,这时需要一种机制来解决这种问题,即自我保护机制。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编写分布式的Erlang程序:陷阱和对策Hans SvenssonDept. of Computer Science and EngineeringChalmers University of TechnologyGothenburg, Swedenhanssv@cs.chalmers.seLars Åke Fredlund*Facultad de Informatica, Universidad Politecnica deMadrid, Spainfred@babel.ls.fi.upm.es摘要为了在Erlang运行时系统基础上开发更可靠的分布式系统和算法,我们研究了Erlang编程语言中分布式的部分。
使用Erlang,把一个运行在单个节点上的程序转换成完全分布式(运行在多个节点上)的应用程序可谓易如反掌(只需要修改对spawn函数的调用,使之在不同节点上产生进程);但尽管如此,Erlang语言和API中仍然有一些阴暗的角落可能在引入分布式运算时带来问题。
在本文中,我们将介绍几个这样的陷阱:在这些地方,取决于进程是否运行在同一个节点上,进程间通信的语义会有显著的差异。
我们同时还提供了一些关于“编写安全的分布式系统”的指导原则。
分类和主题描述 D.3.3【编程语言】:语言构造和特性关键字:可靠性1. 简介我们希望能够编写和调试用到Erlang的分布式进程通信机制的分布式算法,为此我们必须清楚Erlang的分布机制对进程间通信提供了哪些保障——要判断这些保障是否与我们的分布式算法的各种需求相符,首先必须了解它们。
很大部分的研究工作都是在为Erlang编程语言(包括分布机制)开发形式化语义[CS05]。
在实现“分布式Erlang”的模型检查器[FS07]时,我们有几处无法完全肯定形式化语义是否精确描述了Erlang分布层的行为。
但由于并非所有关于分布式支持的重要部分都有文档记录1,做一些试探工作自然是必不可少的。
我们编写了大量程序来测试运行时系统的各种基本特性,同时对运行时系统的源代码也做了检验,从而逐渐勾勒出Erlang语言中分布式部分的真实行为。
我们得到的成果是另一篇关于精化Erlang分布式语义的论文[SF07],以及本文:我们将在文中着重关注Erlang目前提供的分布式支持带来的实际效果——我们将展示哪些代码会出错,并就“如何借助Erlang的分布机制编写可靠的分布式应用”提出我们的建议。
* 该作者由西班牙教育与科学部提供的拉蒙卡哈基金(Ramón y Cajal grant)和DESEFIOS(TIN200615660C0202)、PROMESAS(S0505/TIC/0407)等项目共同资助。
1 当然了,有源代码,如果那也算文档的话……2. 节点内编程Erlang节点内编程的基本工具可说是人所共知了:用send和receive来实现通信;用链接(link)和监视器(monitor)来构造健壮的、在单个进程失败时也不会崩溃的应用程序。
正如前文所说,链接(link)和监视器(monitor)是编写具有高容错性的Erlang程序的基本工具:借助这两种语言特性,当一个进程终止时,它可以向另一个进程发送失败信息。
在分布式应用开发中有一个常见的抽象机制叫做失败侦测器(failure detector),其用途跟Erlang的链接和监视器毫无二致。
请注意,“链接和监视器”机制——监视同一节点上的另一个进程——并不保证被监视的进程在语义上正确:被监视的进程有可能在等待一个永远不会到来的消息,这时它实际上等于已经死掉了,但监视它的进程永远也不会收到“进程终止”的消息。
为此(以及其他一些原因)有必要用计时器(timer)来限制进程通信的等待时间,即便各个进程都在同一节点内。
下面我们将逐一展示节点内通信能够得到的基本保障。
2.1 基本消息传递保障:流语义节点内消息传递的基本保障是:由一个进程发送给另一个进程的消息,只要消息能够送达而没有丢失或重复,就必定是按发送顺序送达的。
在这里,“将一条消息送达进程P”意味着这条消息被放入进程P的收件箱;同时只要消息m被送达P,我们就说P收到了消息m的值——这并不代表P 在此时用receive语句从收件箱中取出的一定是消息m,只代表消息m一定是在收件箱里。
在实际编程中,这项保障意味着:如果进程Q先后发送两条消息(m1和m2)给进程P,那么消息送达的情况必定是下列三种情况之一:•两条消息按发送顺序送达P•只有m1被送达P(等效于P在收到m1之后崩溃)•两条消息都不被送达这种消息发送和接收的顺序保障类似与TCP/IP通道所提供的通信保障——后者常被用于连接多个分布的Erlang节点。
我们把这种通信保障称作流保障(streaming guarantee)。
请注意,这个保障与接收进程的语义无关:该进程是否确实处理收到的消息、是否作出反应,都不在保障之内。
譬如说,进程P可能有个bug,会导致它在收到m1之后立即崩溃;而进程Q则希望P对自己发送的消息作出响应,并且两者已经建立了双向协议。
在这种情况下,前面介绍的通信保障唯一能保证的事情是:如果P没有首先收到并处理m1,它绝不会收到(当然更不会处理)m2。
当然,这里所说的“处理m1”需要在更广泛的意义上来理解:包括忽略m1、不把m1从收件箱中取出(而是等m2送达后先取出后者)、使用“选择性的”receive语句等都应该算作对m1进行了处理。
2.2 多方通信在节点内通信的情况下,还可以对通信模式做更强的假设。
Claessen和Svensson[CS05]给出了一个例子,三个进程(P1、P2和P3)通信如下:•P1发送消息m1给P2•P1发送消息m2给P3•P3把消息m2转发给P2如果上述进程都位于同一节点,那么消息m1必定会在m2之前被送达P2,因为运行时系统只有在P1完成发送之后才会把消息放入接收进程的收件箱。
换句话说,只要各个进程都位于同一节点,应用协议就可以放心地假设m2不会在m1之前被送达P2;但同样的假设在Erlang/OTP将来的版本中可能会有问题2。
3. 跨节点编程当Erlang程序涉及不同节点上的进程时,情况将迥异于单节点编程:不再有一个“大一统”的运行时系统了解当进程崩溃时作出明智决策所需的全部信息。
在一个分布式、多节点的应用中,节点可能在地理上彼此远离,因此一般而言没有办法区分与远端进程(位于另一节点)的通信失败究竟是由于:(1)该节点与发送节点被暂时隔离(例如因为网络故障),还是(2)远端节点的运行时系统崩溃从而终止了其上的所有进程。
为了找出(尽管有可能错误)发生故障的节点,Erlang运行时系统会定期在节点之间发送消息(节拍信号,tick)。
如果N1节点没有收到来自N2节点的tick,那么N2节点就会被认为已经崩溃,N1上所有“链接或者监视N2上进程”的进程就会收到错误通知。
但这时的通信失败有可能只是暂时的:远端节点并未崩溃,稍后可以重新与之建立通信。
尽管分布情况下的通信实现与节点内编程时差异很大,但Erlang承诺通信本身并无不同。
以下文字出自(老的那本)《Concurrent Programming in Erlang》:消息可以被发送给远端进程,本地进程和远端进程之间也可以建立链接,这一切都好像所有进程都运行在同一个节点一样。
远端Pid的另一个特点是:不论从语法上还是语义上,“向远端进程发送消息”都与“向本地进程发送消息”完全一样。
这也就是说,发送给远端进程的消息始终以发送时的顺序送达,不会损坏也不会丢失。
4. 跨节点编程的陷阱为了厘清Erlang的分布语义,我们做了一系列实验来验证这个“节点内编程与跨节点编程无差异”的承诺究竟在多大程度上有效。
作为总结,我们发现两处显著的差异,它们都会在跨节点编程中破坏流保障——这是节点内编程的基本通信保障。
在某些情况下,先发送的消息会丢失,而后发送的消息则会顺利送达。
也就是说,进程Q先后发送m1和m2两条消息给远端节点上的进程P,却有可能发现只有m2被送达,m1则丢2 据我们推测,即便在当前的Erlang/OTP实现下,垃圾收集机制的存在也会使上述假设不能成立;但我们尚未实际观察到这样的情况。
失了。
第一种可能出错的情况是遇到了重复的进程标识符(Pid):在发送m1的过程中进程P所在的节点可能崩溃,然后重启,此时m2就可能被送达重启之后的节点上新生的进程。
第二种情况源自节点之间暂时性的通信故障,这会导致Erlang错误地判定节点已经崩溃,从而悄无声息地抛弃已经发送的消息。
在本节里,我们还会指出另外一些分布式通信的特质(陷阱3和陷阱4),忽视它们也可能导致应用程序出错。
4.1 陷阱1:重复的Pid进程标识符通常被认为是全局唯一的,但它们遵循同一个有穷的结构,因此有可能不是唯一的。
不过只要这个有穷结构足够大,在实际应用中应该可以不用担心会用到重复的进程标识符。
所以,要是你知道在节点崩溃之后创建一个相同Pid的进程有多容易,你肯定会大吃一惊。
在下面的例子中,我们将生成一个进程,确保将它弄死,然后再次与它通信!我们用图1所示的shell脚本来运行这个例子:它一旦发现一个Erlang节点被杀死,就立即重启它。
#!/bin/shNODE=$1while [ 1 lt 2 ]; doerl sname $NODEsleep 1done图1.代码示例:重启节点的脚本这个例子(源代码如图2所示)的原理如下:首先在节点N1上生成一个进程,它负责执行run函数启动实验。
我们假设节点N2已经用图1所示的脚本启动起来。
N1上的进程首先注册退出陷阱(trapping exit),然后把下列指令执行三遍:在N2上创建一个进程并链接到它,然后让它杀死节点N2(调用halt函数),最后等待2秒(以确保N2重启)。
这样一来,我们总共会生成三个进程,它们的Pid都被保存在Pids变量里。
然后我们就等待三条退出消息,以确定所有在N2节点(的不同实例)上生成的进程都已经被杀死了。
最后我们再在N2上生成一个进程,让它执行echo函数。
随后,在N1上调用communicator函数,并传入此前收集到的三个Pid作为参数。
communicator函数会尝试与已经死去的进程通信,而正如我们在图3所示的执行日志中看到的,其中一个被认为早已死去的进程竟然回复了!显然N2上正在执行echo函数的那个新进程有着与之前某个进程相同的标识符。
module(pidReuse).export([start/0,run/0,echo/0,communicator/1]).define(N1,’n1@localhost’).define(N2,’n2@localhost’).start() >spawn(?N1,?MODULE,run,[]).run() >erlang:process_flag(trap_exit,true),Pids =lists:map(fun(N) >Pid1 = spawn_link(?N2,erlang,self,[]),spawn(?N2,erlang,halt,[]),timer:sleep(2000),Pid1end, lists:seq(1,3)),lists:foreach(fun(Pid) >receive {’EXIT’,Pid,_} > ok endend,Pids),spawn(?N2,?MODULE,echo,[]),communicator(Pids).echo() >receive {From,N} > From!{self(),(N+1)} end.communicator(Pids) >lists:foreach(fun(Pid) >io:format("Trying to communicate with: ~w\n(~w)\n",[Pid,term_to_binary(Pid)]),Pid!{self(),5},receive {Pid2,N} >io:format("Recieved ~w from ~w\n(~w)\n",[N,Pid2,term_to_binary(Pid2)])after 2000 >io:format("No reply!\n")endend, Pids).图2. 代码示例:Pid被重复使用Trying to communicate with: <4888.40.0>(<<131,103,100,0,12,...,49,49,56,0,0,0,40,0,0,0,0,3>>)Recieved 6 from <4888.40.0>(<<131,103,100,0,12,...,49,49,56,0,0,0,40,0,0,0,0,3>>)Trying to communicate with: <4888.40.0>(<<131,103,100,0,12,...,49,49,56,0,0,0,40,0,0,0,0,1>>)No reply!Trying to communicate with: <4888.40.0>(<<131,103,100,0,12,...,49,49,56,0,0,0,40,0,0,0,0,2>>)No reply!图3. 输出:Pid被重复使用4.1.1 分析显然当节点崩溃并重启之后,很快Pid就出现了重复。