高扩展软件架构设计

从最简单的水平来看,可伸缩性就是做更多的事情。更多的事情可以是响应更多的用户请求,执行更多的工作,或处理更多的数据。设计软件这件事本身是复杂的,而让软件做更多的工作也有其特有的问题。这篇文章针对构建可伸缩软件系统提出了一些原则和方针。

  1. 减少处理时间

  增加应用所做工作数量的一个方法就是减少完成单项工作所花费的时间。举例来说,减少处理一个用户请求所需的时间意味着你能在同样长的时间内处理更多的用户请求。这里有一些本原则适用的例子和一些可能的实现策略。

并置(Collocation):通过并置数据和代码,减少因获取所需数据而产生的必要开销。

缓存:如果数据和代码不能并置,就缓存数据,以减少反复取数据的开销。

池化:通过池化昂贵的资源,减少与其使用相关的开销。

并行化:通过分解问题、并行化独立的步骤,减少完成一个工作单元所需的时间。

分区处理:通过分割处理代码、并置相关的分区,尽可能将相关的处理过程集中在一起。

远程处理:减少访问远程服务所花费的时间,比如可以通过更粗粒度地划分接口。远程还是本地是明确的设计决策,不能随意来回更动,这一点应当牢记。还要考虑分布式计算的第一准则——不要分布你的对象。

  软件开发人员总爱在不需要的地方引入抽象和层。是的,这些概念对软件组件之间的解耦来说是很好的工具,但它们可能会增加复杂性、影响性能,尤其是在每层的数据表示之间都需要转换的情况下。因此,减少处理时间还要注意保证抽象不要过于抽象化,并且没有过多的分层。另外,对于我们视为理所当然的运行时服务,有必要理解其成本,因为除非它们提供了特定的服务水平协议,否则很有可能最终会成为应用中的瓶颈。

  2. 分区

  减少单个工作单元的处理时间能达到不错的效果,但当你达到单进程方案的极限,最终还是需要对系统作水平伸缩。在典型的Web应用中,水平伸缩可能很简单,只要加入更多的Web服务器来处理用户请求,再给它们加上负载均衡就行了。但是,你可能会发现总体架构的某些部分会成为资源争用的焦点,因为一切东西都会在同一时间变得忙碌起来。一个很好的例子就是所有Web服务器后端的单一数据库服务器。当这个单一的数据库服务器变成瓶颈时,你必须改变方法,其中一种方式就是采用分区策略。简而言之,这涉及到将架构的单个部分分解成更小、更容易管理的部分。将单个的元素分割成更小的部分能实现水平伸缩,这恰恰也是 eBay这样的大型网站采用、以此来确保它们的架构可伸缩的技术。分区是一个很好的解决办法,尽管你可能会发现牺牲了一致性。

  至于如何分割你的系统,那要看情形而定。真正无状态的组件能简单地作水平伸缩,将工作负载分散到所有实例上,让组件的所有实例都能有效地运行。另一方面,如果需要维护某状态,你需要找到一种工作量分割策略能允许有状态组件的多重实例,让每个实例负责工作和/或数据的一个独特的子集。

  3. 可伸缩性在于并发

  可伸缩性天生就和并发联系在一起;毕竟,它就是要在同样的时间内做更多的工作。像EJB早期版本这样的技术试图提供一种简化的编程模型,鼓励我们编写单线程的组件。遗憾的是,组件往往要依赖于其它组件,还是导致了并发问题。如果没有考虑并发,系统中的数据会很容易被损坏。另一方面,围绕并发做了太多的保护会导致系统实质上变成串行的,限制了伸缩的能力。并发编程不是很难做到,在构建可伸缩系统的时候,有一些简单的原则会有所帮助。

如果你确实需要持有锁(比如本地对象、数据库对象等),试着尽可能短地持有它们。

设法减少对共享资源的争用,并尽可能是争用避开关键处理路径(比如通过异步调度工作)。

任何针对并发的设计都需要预先完成,以便能被充分地理解哪些资源可以被安全共享、哪里可能会是潜在的可伸缩性瓶颈。

  4. 必须知道需求

  为了构建一个成功的软件系统,你需要知道你的目标是什么、你针对什么去做。尽管功能性需求往往是明确的,但常常会缺少非功能性需求(或系统质量需求)。如果你真是需要构建一套高可伸缩的软件,那你首先需要调查清楚关键组件/工作流的以下特质:

目标平均性能和峰值性能(即响应时间、延迟等)。

目标平均负荷和峰值负荷(即并发用户、信息量等)。

性能和可伸缩性可接受的极限。

  性能也许不是最紧要的方面,但你必须尽早知道这个信息,因为处理可伸缩性的方法会由性能需求决定。

  5. 持续测试

  理解了需求就可以开始设计和构建解决方案。我们提出的设计、编写的代码实际上都是静态的,所以你在执行之前不能完全断定它会怎样运转。此外,所有关于性能和可伸缩性的决策应该由证据支持的原因也在于此,而且应当从项目一开始就收集和审核这些证据,此后也要一直继续。换句话说,就是设立贯穿系统的可度量目标,证实并度量实际的性能,并在项目的各个阶段考虑性能。

  最常犯的错误之一是,我们对系统性能和可伸缩性的见解会被我们自己的经验或道听途说所混淆。你可能要审核对工程做出的其它决策,这样做的原因之一是要满足系统的非功能性特性。比如说,非功能性需求可能会影响你选择不使用标准,改用非主流/流行的一些东西。非功能性需求可能会打破僵化的教条,证据胜过教条。

  6. 架构先行

  或许对构建可伸缩的系统来说最重要的原则是,如果你需要使系统具备这样的性质,就必须预先设计出这样的性质。很多人(包括我自己)陷入的陷阱,就是以为可以构建一个应用,它会自动地垂直伸缩(scale up)或水平伸缩(scale out),尤其是在J2EE刚出现的时候。设计为可水平伸缩的应用几乎总能垂直伸缩,但是设计为垂直伸缩的应用几乎不可能水平伸缩。大多数应用能通过在更加强大的硬件上运行来垂直伸缩,但水平伸缩却是一个更为复杂的问题。比如说,你怎么确保数据在应用实例之间保持一致性?你如何使你的单例和同步代码块跨线程工作?

  当然,预先思考这件事情不一定等同于做一个瀑布式的、预先的大设计。迭代和敏捷过程都是助力,它们能提供一个框架帮助我们可以做出刚好够用的设计来解决问题。要务实。哦,不管我们自认为是多么擅长于设计可伸缩的应用,不要相信自己、尽早地编写/测试代码才是最好的举动。

  7. 着眼于全局

  最后,记着要着眼于全局——看到树木之前先看看森林。对我们来说,在细粒度代码级别调整组件确实很容易,但最终需要优化的却是作为一个整体的系统。关注每一个环节的性能和可伸缩性,必要时牺牲局部的优化。如果你需要使用性能分析工具确定瓶颈,不妨去做,但在对全局的性能有所认识之前先不要急于动手。由于性能与整个系统所有等待时间的集合成反比,任何等待时间增加得比负载还快的操作都会成为问题。尽管说了这么多,但我还想指出,如果你发现满足性能和可伸缩性目标很困难,那就有必要怀疑一下是否选择了正确的架构。还是那句话,着眼于全局,确保有人在承担架构师的责任。

  总结

  这篇文章针对构建可伸缩应用提出了一些原则和方针,覆盖了软件开发过程中许多不同的方面。无论谁要构建可伸缩的系统,我能给他的最好建议就是你需要明确地考虑并设计你的系统。可伸缩性不是魔术,它也不会无偿获得。最后一点,更快的硬件也许能救你于一时,但还是不要依赖它为妙!

时间: 2024-11-08 02:01:02

高扩展软件架构设计的相关文章

软件架构设计系列总结

架构引用维基百科:软件体系结构是构建计算机软件实践的基础.与建筑师设定建筑项目的设计原则和目标,作为绘图员画图的基础一样,一个软件架构师或者系统架构师陈述软件构架以作为满足不同客户需求的实际系统设计方案的基础.从和目的.主题.材料和结构的联系上来说,软件架构可以和建筑物的架构相比拟.一个软件架构师需要有广泛的软件理论知识和相应的经验来实施和管理软件产品的高级设计.软件架构师定义和设计软件的模块化,模块之间的交互,用户界面风格,对外接口方法,创新的设计特性,以及高层事物的对象操作.逻辑和流程.软件

软件架构设计箴言理解

如果你对项目管理.系统架构有兴趣,请加微信订阅号"softjg",加入这个PM.架构师的大家庭 今天和师弟聊天聊到他们项目开发,有些同事总是提前考虑性能优化,需求变更又是一大堆的重写,让我想起了Donald Knuth 提到的:对软件的过早地优化是万恶的根源.这里就简单的说几条重要的软件名人哲学. 1:软件中唯一不变的就是变化. 在软件开发过程中需求是不停的变化,随着客户对系统的认识,和现有开发功能和软件的认识,也许以开始他提出的需求就是背离的.记得网上有一句笑话,师说需求变化的: 程

小议软件架构设计要点

如何更好地进行软件架构设计,这是软件工程领域中一个永恒的重点话题.过去几十年来,国际软件工程界在软件架构设计方面已经获得了长足发展,大量图书.文章和文献记载了这方面的成熟经验与成果.软件架构设计往往是一件非常复杂的工作,涉及到很多细节和方方面面,可探讨的话题也非常之多.囿于篇幅限制,以下只能根据笔者个人理解,遴选出软件架构设计的个别要点,结合当前流行的敏捷软件工程思想,与大家分享一下自己在软件架构设计方面的心得和体会. 架构决定成败 软件架构是软件产品.软件系统设计当中的主体结构和主要矛盾.任何

浅谈企业应用软件架构设计过程

1.引言 本文不是学术性文章,也不是某些标准化理论的阐述,而是根据所从事J2EE应用软件架构设计工作的经验,谈谈自己对软件架构设计过程的理解,希望能让一些徘徊于门口的同学能对企业应用软件架构设计的目标.价值与方法有个大致概念.文中所举例子及分析方法受个人经验背景约束,可能在一定程度上会存在误导性,软件架构设计过程大同小异,例子主要还是用于辅助说明设计过程. 对于架构设计,如果用建筑来比拟的话,有点类似这样:这是我们将修建一座大教堂,甲方有这样的一些特殊要求,比如大堂要能容纳5000人,中间不能有

【转载】数据库软件架构设计些什么

缘起:受@萧田国 萧总邀请,上周五晚上在"高效运维1号群"内分享了<58同城数据库软件架构设计与实践>(这个topic今年在数据库大会上分享过),应组织方要求,发出纪要. 一.基本概念 二.数据库架构设计思路 (1)可用性 (2)读性能 (3)一致性 (4)扩展性 一.基本概念 概念一"单库" 概念二"分片" 分片解决的是"数据量太大"的问题,也就是通常说的"水平切分". 一旦引入分片,势必有&

软件架构设计的七大原则

软件架构设计有七大原则,分别是: 1.开闭原则 2.依赖倒置原则 3.单一职责原则 4.接口隔离原则 5.迪米特法则(最小知道原则) 6.里氏替换原则 7.合成/聚合复用原则 下面分别具体说明: 1.开闭原则  :对扩展开放,对修改关闭    说的是,再设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展.换言之,应当可以在不必修改源代码的情况下改变这个模块的行为,在保持系统一定稳定性的基础上,对系统进行扩展. 例如:一般软件功能的升级就需要符合开闭原则,即不去修改原来的代码,而是去增

软件架构设计的目的

软件架构设计的目的简单说就是在保持软件内在联系的前提下,分解软件系统,降低软件系统开发的复杂性,而分解软件系统的基本方法无外乎分层和分割.但是在保持软件内在联系的前提下,如何分层分割系统,分层分割到什么样的粒度,并不是一件容易的事,这方面有各种各样的分解方法,比如:关注点分离,面向方面,面向对象,面向接口,面向服务,依赖注入,以及各种各样的设计原则等, 耦合可以分为以下几种,它们之间的耦合度由高到低排列如下: (1) 内容耦合:一个模块直接访问另一模块的内容,则称这两个模块为内容耦合. 若在程序

亚马逊AWS在线系列讲座——基于AWS云平台的高可用应用设计

设计高可用的应用是架构师的一个重要目标,但是基于云计算平台设计高可用应用与基于传统平台的设计有许多不同.云计算在给架构师带来了许多新的设计挑战的时候,也给带来了许多新的设计理念和可用的服务.如何在设计应用的时候充分利用云平台的各种特点是基于云计算设计的一个重要条件.在这个在线讲座中,我们将以亚马逊AWS云平台为例,讨论如何设计一个高可用应用. 我们先会根据AWS服务是否天然高可用.高容错的特点把常见的AWS服务分类.比如AWS把下面服务设计成高可用和高容错的服务: ·     Amazon S3

软件架构设计学习总结

软件架构设计就是软件系统的'布局谋篇',是软件抽象发展到一定阶段的产物.软件设计人员学习软件架构知识,旨在站在较高的层面上,整体的解决好软件的设计,复用,质量和维护等方面的实际问题.本文以图形的方式进行总结归纳,从软件架构的描述,设计,风格,评价,形成方法进行阐述. 软件架构设计总述: 软件架构的概念 软件架构的意义 软件架构的风格 分层架构 面向服务的架构(SOA) 特定领域的架构(DSSA) 软件产品线 基于架构的软件开发(ABSD) 软件架构与质量属性 软件架构评估 -----------