《可扩展Web架构与分布式系统》由会员分享,可在线阅读,更多相关《可扩展Web架构与分布式系统(22页珍藏版)》请在金锄头文库上搜索。
1、开放源代码已经成为一些大型网站的基本原则。而在这些网站成长的过程中, 一些优秀的实践经验和规则也出现在他们的结构中。本文旨在介绍一些在大型 网站结构设计的过程中需要注意的关键问题以及实现目标的基础工作。本文侧重于介绍网络系统,尽管一些准则在其他分布式系统中也是适用的。1.1.1.1. webweb 分布式系统的设计原则分布式系统的设计原则搭建和运营一个可伸缩的 web 站点或者应用程序意味着什么?在原始层面上这 仅仅是用户通过互联网连接到远程资源-使系统变得可伸缩的部分是将资源、或 者访问的资源,分布于多个服务器上。像生活中大多数事情一样,当构建一个 web 服务时花时间提前做好计划从长远 看
2、来还是很有帮助的;了解一些注意事项和大网站背后的权衡原则可以在创建 小型网站时做出更明智的决定。以下是一些影响大规模 web 系统设计的关键原 则:可用性可用性: :对于很多公司来说一个网站的正常运行时间是非常关键的声誉和 功能,像一些大型的在线零售系 统,即使一分钟的宕机都有可能导致数 千或者数百万美元的损失,因此设计系统的时时可用性和弹性的错误处 理机制既是一个基本业务也是一个技术要求。 高可用分布式系统需要仔 细考虑关键组件的冗余,分系统失败后能快速修复,并且当问题出现时 优雅型降级。性能性能: :网站的性能正在变成大多数站点考虑的一个重要的方面,网站的速 度影响正常使用和用户的满意度,
3、同样影响搜索的排名,这也是影响网 站收益和保留用户的一个因素。因此,创建一个快速响应和低延迟的系 统是非常关键的。可靠性可靠性: :一个系统需要具备可靠性,比如同一个数据的请求始终返回同样 的数据响应 。如果数据改变或者被更新,那么同样的数据将返回一个新 的数据。用户需要知道一些东西被写入系统或者被存储到系统后,系统 会保持不变并且可以在以后恢复到合适的位置。可伸缩性可伸缩性: :当谈到任何大型的分布式系统时,规模大小只是考虑的其中一 个方面,同样重要的是增强处理较大规模的负载性能所做的努力,这通 常称为系统的可伸缩性。可伸缩性可以代表系统很多不同的参数:额外 流量的处理量,添加存储容量的便意
4、性,甚至事务的处理量。可管理性可管理性: : 设计一个系统可以方便操作是另一个重要的考虑方面,系统 的可管理性等同于操作的可伸缩性:维护和升级。可管理性需要考虑的 事情是当问题发生时方便诊断和了解问题,易于升级和修改,以及系统 能简单性的操作(即,例行的操作有没有失败和异常?)成本成本: : 成本是一个重要的因素。很明显这包含硬件和软件成本,但同样 重要需要考虑的其他方面是部署和维护系统的成本。开发者构建系统花 费的大量时间,运维部署时间,甚至培训时间都需要考虑,成本是总体 成本。以上每个原则都为设计分布式 web 架构提供了基础决策。然而,他们也能彼此 互斥,例如要实现某个目标就要以另外的作
5、为代价。一个基本的例子:选择通 过单纯增加更多的服务器(可扩展性)来增加地址容量,是以可管理性(你必 须操作增加的服务器)和成本(服务器的价格)为代价的。当设计任何的 web 应用程序时,考虑这些关键原则都是很重要的,即使得承认 一个设计可能要牺牲它们之中的一个或者多个。1.2.1.2. 基础基础当设计一个系统架构时,有一些东西是要考虑的:正确的部分是什么,怎样让 这些部分很好地融合在一起,以及好的折中方法是什么。通常在系统架构需要 之前就为它的可扩展性投资不是一个聪明的商业抉择;然而,在设计上的深谋 远虑能在未来节省大量的时间和资源。这部分关注点是几乎所有大型 web 应用程序中心的一些核心
6、因素:服务、冗余、 划分和错误处理。每一个因素都包含了选择和妥协,特别是上部分提到的设计 原则。为了详细的解析这些,最好是用一个例子来开始。实例:图片托管应用实例:图片托管应用有时候你可能会在线上传一张图片。对于那些托管并负责分发大量图片的网站 来说,要搭建一个既节省成本又高效还能具备较低的延迟性(你能快速的获图 片)的网站架构确实是一种挑战。我们来假设一个系统,用户可以上传他们的图片到中心服务器,这些图片又能 够让一些 web 链接或者 API 获取这些图片,就如同现在的 Flickr 或者 Picasa。为了简化的需要,我们假设应用程序分为两个主要的部分:一个是上 传图片到服务器的能力(通
7、常说的写操作),另一个是查询一个图片的能力。 然 而,我们当然想上传功能很高效,但是我们更关心的是能够快速分发能力, 也就是说当某个人请求一个图片的时候(比如,一个 web 页面或者其它应用程 序请求图 片)能够快速的满足。这种分发能力很像 web 服务器或者 CDN 连接服 务器(CDN 服务器一般用来在多个位置存储内容一边这些内容能够从地理位置 或者物理上 更靠近访问它的用户,已达到高效访问的目的)气的作用。系统其他重要方面:对图片存储的数量没有限制,所以存储需要可扩展,在图像数量方面需 要考虑。图片的下载和请求不需要低延迟。如果用户上传一个图片,图片应该都在那里(图片数据的可靠性)。系统
8、应该容易管理(可管理性)。由于图片主机不会有高利润的空间,所以系统需要具有成本效益。Figure 1.1 是一个简化的功能图。Figure 1.1: 图片主机应用的简化架构图在这个图片主机的例子里,可遇见系统必需快速,它的数据存储要可靠以及这 些所有的属性都应该高度的可扩展。建立这个应用程序的一个小版本不是很重 要 而且很容易部署在单一的服务器上;然而,这不是这节里的感兴趣部分。假 设下我们想建一个会增长到和 Flickr 痛让规模的东西。服务服务当要考虑设计一个可扩展的系统时,为功能解耦和考虑下系统每部分的服务都 定义一个清晰的接口都是很有帮助的。在实际中,在这种方式下的系统设计被 成 为面
9、向服务架构(SOA)。对于这类型的系统,每个服务有自己独立的方法 上下文,以及使用抽象接口与上下文的外部任何东西进行交互,典型的是别的 服务的公 共 API。把一个系统解构为一些列互补的服务,能够为这些部分从别的部分的操作解耦。 这样的抽象帮助在这些服务服、它的基础环境和服务的消费者之间建立清晰的 关系。建立这种清晰的轮廓能帮助隔离问题,但也允许各模块相对其它部分独 立扩展。这类面向服务设计系统是非常类似面向对象设计编程的。在我们的例子中,上传和检索图像的请求都是由同一个服务器处理的;然而, 因为系统需要具有伸缩性,有理由要将这两个功能分解为各由自己的服务进行 处理。快速转发(Fast-for
10、ward)假定服务处于大量使用中;在这种情况下就很容易 看到,读取图像所花的时间中有多少是由于受到了写入操作的影响 (因为这两 个功能将竞争使用它们共享的资源)。取决于所采用的体系结构,这种影响可能是巨大的。即使上传和下载的速度完全相同(在绝大多数 IP 网络中都不 是 这样的情况,大部分下载速度和上传速度之比都至少设计为 3:1),文件读取 操作一般都是从高速缓存中进行的,而写操作却不得不进行最终的磁盘操作 (而且 可能要写几次才能达成最后的一致状态)。即使所有内容都已在内存中, 或者从磁盘(比如 SSD 磁盘)中进行读取,数据库写入操作几乎往往都要慢于 读取操作。 (Pole Positi
11、on 是一个开源的 DB 基准测试工具, http:/polepos.org/,测试结果参见http:/ )这种设计另一个潜在的问题出在 web 服务器上,像 Apache 或者 lighttpd 通常 都有一个能够维持的并发连接数上限(默认情况下在 500 左 右,不过可以更高) 和最高流量数,它们会很快被写操作消耗掉。因为读操作可以异步进行,或者 采用其它一些像 gizp 压缩的性能优化或者块传输编码方 式,web 服务器可以 通过在多个请求服务之间切换来满足比最大连接数更多的请求(一台 Apache 的 最大连接数设置为 500,它每秒钟提供近千次读请求服 务也是正常的)。写操 作则不同
12、,它需要在上传过程中保持连接,所以大多数家庭网络环境下,上传 一个 1MB 的文件可能需要超过 1 秒的时间,所以 web 服务器 只能处理 500 个这 样并发写操作请求。对于这种瓶颈,一个好的规划案例是将读取和写入图片分离为两个独立的服务, 如图 Figure 1.2.所示。这让我们可以单独的扩展其中任意一个(因为有可能 我们读操作比写操作要频繁很多),同时也有助于我们理清每个节点在做什么。 最后,这也避免 了未来的忧虑,这使得故障诊断和查找问题更简单,像慢读问 题。这种方法的优点是我们能够单独的解决各个模块的问题-我们不用担心写入和检 索新图片在同一个上下文环境中。这两种服务仍然使用全球
13、资料库的图片,但 是它们可通过适当的服务接口自由优化它们自己的性能(比如,请求队列,或 者缓存热点图片-在这之上的优化)。从维护和成本角度来看,每个服务按需进 行独立 规模的规划,这点非常有用,试想如果它们都组合混杂在一起,其中一 个无意间影响到了性能,另外的也会受影响。当然,上面的例子在你使用两个不同端点时可以很好的工作(事实上,这非常 类似于云存储和内容分发网络)。虽然有很多方式来解决这样的瓶颈,但每个 都有各自的取舍。比如,Flickr 通过分配用户访问不同的分片解决这类读/写问题,每一个分片 只可以处理一定数量的用户,随着用户的增加更多的分片被添加到集群上(参 看“Flickr 缩影”
14、的描述 http:/ 2007-presentation-file.html)。 在第一个例子中,可以根据实际用途更简 单的规划硬件资源(在整个系统中读和写的比例),然而,Flickr 规划是根据 用户基数(假定每个用户拥有相同的资 源空间)。在前者中一个故障或者问题 会导致整个系统功能的下降(比如,全部不能写入文件了),然而 Flickr 一个 分片的故障只会影响到相关的那部分用 户。在第一个例子中,更容易操作整个 数据集-比如,在所有的图像元数据上更新写入服务用来包含新的元数据或者检 索-然而在 Flickr 架构上每一个分片都 需要执行更新或者检索(或者需要创建 个索引服务来核对元数据-
15、找出哪一个才是实际结果)。冗余冗余(Redundancy)(Redundancy)为了优雅的处理故障,web 架构必须冗余它的服务和数据。例如,单服务器只 拥有单文件的话,文件丢失就意味这永远丢失了。丢失数据是个很糟糕的事情, 常见的方法是创建多个或者冗余备份。同样的原则也适用于服务。如果应用有一个核心功能,确保它同时运行多个备 份或者版本可以安全的应对单点故障。在系统中创建冗余可以消除单点故障,可以在紧急时刻提供备用功能。例如, 如果在一个产品中同时运行服务的两个实例,当其中一个发生故障或者降级 (degrade),系统可以转移(failover)到好的那个备份上。故障转移(Failover
16、) 可以自动执行或者人工手动干预。服务冗余的另一个关键部分是创建无共享(shared-nothing)架构。采用这种架 构,每个接点都可以独立的运作,没有中心”大脑”管理状态或者协调活动。 这可以大大提高可伸缩性(scalability)因为新的接点可以随时加入而不需要特 殊的条件或者知识。而且更重要的是,系统没有单点故障。所以可以更好的应 对故障。例如,在我们的图片服务应用,所有的图片应该都冗余备份在另外的一个硬件 上(理想的情况下,在不同的地理位置,以防数据中心发生大灾难,例如地震,火灾),而且访问图片的服务(见 Figure 1.3.)-包括所有潜在的服务请求-也应该冗余。(负载均衡器是个很好的方法冗余服务,但是下面的方法不仅仅 是负载均衡)Figure 1.3: 使用冗余的图片存储分区分区我们可能遇见单一服务器无法存放的庞大数据集。也可能遇到一个