`

erlang架构原理整理

阅读更多
架构就是一种思考世界的方式。
 
我们必需得把我们看待世界的方式---->
 
实用的手册+一组流程------->
 
它们可以告诉我们如何使用我们看待世界的特定的方式来构造一个特定的系统。
 
 
软件架构通过下面的一些方面来描述
 
1、问题领域(我们架构是为解决什么类型的问题而设计的?)   
     
     软件的架构不是通用,而是为了解决某一类特定问题而设计的。
 
     问题描述:
  • 系统能够应对大量的并发活动
  • 能够在指定的时间内完成任务(如果在指定时间内没有完成,则【终止|重试指定的次数后终止】,编写这样的系统会管理数很多计时器)
  • 可以跨计算机分布运行
  • 系统能够控制硬件
  • 软件系统比代码量比较大
  • 有复杂功能(市场的压力迫使系统的开发和部署有很多复杂的特性,很多特性之间的关系还没有被很好理解时,就必须要上线部署,在系统运行期间,这些特性很可能需要以多种方式 进行修改、维护和扩展,功能和软件的升级必须“线上运行”,也就是说,不能让系统停下来)
  • 可以不间断运行多年
  • 满足苛刻的质量和可靠性的要求
  • 必须提供容错功能,包括硬件失灵和软件错误
 
 
2、哲学(软件构造背后的原理是什么,它的核心思想是什么?,如何才能够构建出软件在错误的时候具有合理行为的可容错的软件系统)
 
  • 列出目标------>与目标对应的任务,并按任务复杂度进行排序
  • 尽力去完成复杂度高的任务
  • 如果出现的问题比较麻烦时,暂时放一下,先去解决别的任务,别和任务处理完时,在处理前面的问题
  • 强有力的任务封装隔离错误的蔓延。
  • 每个任务必须经过严格的测试,才可以集成到主程序中
  • 构建可容错软件系统的核心就是故障隔离。
     
     为了解决故障隔离的问题,我们选择了进程,因为进程之间是互相不受影响的
     
     我们用语言实现进程而不是用宿主机提供的原因
  • 可以一致的运行在不同的操作系统上
  • 基于语言的进程比传统的操作系统进程要轻量的很多,而且很高效
  • 我们的系统对操作系统要求很少。          
     应用程序是通过大量互相通信的并行进程构建起来的,我们采用这种方式的原因
  • 它提供了一个架构基础设施
    我们可以用一组互相通信的进程组织起我们的系统,通过枚举出系统中所有进程,并定义出进程间消息传递的通道,我们就可以很方便把系统划分成良好的子部件,并可以对这些子部件进行单独实现和测试,这种方法学也是SDL系统设计方法学的最高境界。
  • 巨大的潜在效率
    设计成以许多独立的并行进程来实现的系统,可以很方便地实现在多处理器上,或者运行在分布式的处理器网络上,注意,这种效率的提升是潜在的,只有当应用程序可以被分解成许多真正独立的任务时,才能产生实效,如果任务之间有很强的数据依赖,这种提升往往是不可能的

  • 故障隔离(本质进程隔离
    没有共享数据的并发进程提供了一种强大的故障隔离的方法,一个并发进程的软件错误不会影响到系统中的其他运行的进程。
    每一项独立的活动都在一个完全独立的进程中来执行,这些进程没有共享数据进程之间只通过消息传递{发送即祈祷}来方式进行通信,消息传递的方式是异步每个消息都是通过拷贝,这就限制了软件错误造成的影响。
    故障即停:当一个处理器出错时,应当立即停止,而不是继续运行。
    故障曝光性质:当一个处理器发生故障时,系统中的其他处理器应该得到通知,故障原因必须交代清楚
    持久存储性质:处理器的存储器应当分为持久存储器(处理器器崩掉时,数据依然存在),和临存储器。
     
    面向并发语言(COPL)
     
  • 基于现实世界的编程
    我们常常想编写一些对现实世界建模或都和其交互的程序,用COPL编写这样的程序相当容易,它只我下面的在个活动
    (1)、从真实的世界中的活动中识别出真正的并发活动
    (2)、识别了并发活动之间的所有消息通道
    (3)、写下能够在不同的消息通道中流通的所有消息
    然后我们来编写程序,程序的结构要严格保持一问题的结构一致,则每一个真实世界的活动都严格映射到我们编程语言的一个并发进程上,如果从问题到程序的映射比例为1:1,我们就说程序与问题是同构的。

    在分析问题时,我们还必须为我们的模型选择一个合适的粒度,比如,我们在编写一个即时通信信息时,我们使用每个用户一个进程的方式,而不是将用户身上的每一个原子对就到一个进程。

  • COPL的特征
    (1)、应该支持进程,每一个进程应该可以看作是一个自包含的虚拟机器
    (2)、运行在同一台机器上的各个进程应该被隔离。一个进程中的故障不能对其它进程产生影响 。
    (3)、每个进程必须用一个唯一的,不可仿造的标识符来标识,我们称之为进程PID,
    (4)、进程之间没有共享状态。只通过消息来传递数据,只知道PID,就可以发送消息
    (5)、消息传递被认为是不可靠的,无传输保障的。
    (6)、一个进程可以检测另一个进程的故障,并可以知道发生故障的原因(但是故障的原因不一定是正确的,如我们可能收到已经死亡的通知消息,然而事实上是发生了一个网络错误)

     
    系统需求
     并发性  : 支持并发性,创建或销毁一个并发进程的计算开销一定要非常小,即使创建大量的并发进程,也不应该带来空难
     错误封装:一个进程中发生的错误一定不能破坏系统中其他的进程
     故障检测: 一定可以检测到本地异常和远程异常
     故障识别:我们要能够识别出异常产生的原因
     代码升级:要有某种机制来替换执行中的代码,而不必停下系统
     持久存储:我们需要把数据按某种策略存储下来,以便恢复一个已经崩溃的系统
 
     语言要求
     封装原语:语言必须有多种手段来限制错误的蔓延,应当可以把一个进程隔离起来,免得他破坏其它进程。
     并发性   :语言必须提供和种轻量化的机制来创建并行进程,以及在进程间发送消息,进程的上下文切换,消息传递必须非常高效。并行进程还必须以一种合理的方式来分享CPU时                    间,以便当前使用的CPU进程不会垄断CPU,而其他的进程处于“准备好”状态而得不到处理
     错误检测原语:语言应该允许一个进程监控另一个进程,从而检测被监控进程是否因任何原因而终止
     位置透明:如果我们知道了一个进程Pid,我们就应该可以向它发送消息,无论它是本地还是远程的
     动态代码升级:应该可以动态替换运行时系统的代码。注意因为许多进程可能同时按照同一份代码在运行,所以我们需要一种机制,来允许现有的进程按照“老”的代码在运行, 而同时“新”进程按照修改后的代码运行。
 
      
     
3、软件架构指南(我们如何来规划一个系统)
 
     我们需要一个明确的架构指南。系统由一个团队来编写和维护,所以对所有参与人员来说,理解系统的架构和它的潜在哲学是很重要的。
     软件构指南,主要包括编程规则集、例子程序和培训资料等
 
4、预先定义好的部件
 
     以“从一组预先定义的部件中选择”的方式进行设计远比“从头设计 ”的方式要来的 容易
 
     库需求
     基本的程序库提供:
     持久存储:由它存储故障恢复信息
     设备驱动程序:它允许我们升级运行系统中的代码
     运行基础:它解决系统的启动、停止和错误报告问题
 
     应用程序库
     OTP库是我们提供了用来构建可容错系统的一个完整的设计模式库
   
 
5、描述方式 (如何描述某一部件的接口,如果描述两个部件之间的通信协议,如何描述系统中静态和动态的结构?)
 
6、配置方式
     
     我们如何启动,停止和配置我们的系统?我们可以在系统运行过程中对系统进行升级。
 
     
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics