事物是发展变化的,事物的发展是一个过程。时间上,事物的发展过程呈现 阶段 性特征;空间上,每个阶段必然有不同的具体业务 场景 。
故从时空观来看,网站架构方法大致不外乎两种:
时间上:分阶段看待
对于架构而言,没有银弹,只有trade-off。架构师则需要阶段性场景化思考,然后权衡利弊,解决问题。
任何大的事物必然都是从小事物发展起来的,当系统业务足够简单时,实现一个网站架构只需要一些通用的解决方案,如早期的LAMP架构,如现今的云开发模式以及无服务架构。
作为人与机器的『中间人』- 程序员,负责把业务需求转换成业务代码与数据。随着业务的发展以及需求不断迭代与丰富,网站系统的复杂度自然从低到高转变,网站的量(包括用户量和数据量)从小到大,从大量到海量,网站的类型(包括用户操作类型与数据类型)从单纯到丰富。程序员在负责『翻译』工作的同时,则还需要解决这些增长过程中出现的各种问题,保证整个组织实现又好又快发展。
解决问题是工程师的天职,更是程序员的宿命。Ta需要解决当下业务发展中遇到的问题,更需要解决未来业务发展规模化的问题。
即程序员归根结底解决的是变化这个命题,细分到具体操作层面也可以分为下面三类:
解决 业务 变化问题:
从简单到复杂,保证系统高可用 - 分层&解耦&冗余
从存量到增量,保证系统可伸缩与可扩展 - 集群/分布式/分布式集群
解决 用户 变化问题,保证系统高并发 - 单机C10K-》集群-》分布式-》分布式集群
解决 数据 变化问题:保证系统高性能 - 缓存
从量少到量多
抛开编程语言与具体框架的细节,这里只讨论方法。简单的问题可单枪匹马,复杂的问题则需要分而治之。下面将从分与治两个方面来讨论具体的网站架构方法。
空间上,分这个动作可以分为两类:
垂直划分:分层
面对复杂问题时,第一步要想到的就是分层。
当网站发展到一定规模,单一的通用架构已无法处理这种复杂性,这时架构分层不可避免。
分层的概念在网络协议上表现的淋漓尽致,通过将一个数据传输任务划分为多个层级,下层向上层提供完整抽象,每层各司其职。网站系统也可将系统在纵向维度上切分成几个部分,每一部分专注于某一方面,职责相对单一,逻辑清晰,然后通过上层对下层的依赖和调用组成一个完整的系统。根据网站系统的职能,大致可以分为四层:
表示层:网站的UI展示,负责用户与网站系统的交互。
应用层:主要负责具体业务逻辑处理。调用下层服务实现业务需求。
服务层:负责为应用层提供细粒度的业务服务。
当网站规模进一步扩大,功能越发繁多复杂,服务和数据处理的种类也越来越多,这时针对每层进行更为细粒度的划分-垂直分割势在必行。如在服务层,可根据不同业务场景进行分割,如将整个电商服务拆分出订单服务,支付服务,商品服务等;如在数据层,可根据数据类型将数据分为文本、图片、视频、日志等类型数据,然后针对每一种类型的数据采用适合的存储结构或服务:文本类型数据使用数据库存储;图片/视频使用CDN存储;日志类型数据使用ES存储等等。
将这些不同功能/类型的服务/数据分割开来,封装成高内聚低耦合的模块单元,一方面有助于降低系统的复杂度,减少软件的开发和维护成本;另一方面,也便于不同模块的分布式部署,提高网站的并发处理能力和可伸缩、可扩展能力。
分完之后下一步则是治之。
分层和分割之后的模块间必然存在依赖关系,即必然存在耦合。解耦是一种理想状态,理论上相互联系的模块间耦合度不能为零,但是耦合度可以降低,即所谓的解耦。
2.1.1)异步化:时间形式上的解耦
耦合的模块之间存在连接,有连接在某个时刻就可能会引起阻塞(存在等待的场景)。为了减少这种模块之间阻塞问题,提高效率,可以将一个流程或一条业务线操作分成多个阶段,每个阶段之间通过共享数据(即消息队列或缓冲区)的方式进行协作,这就是异步化。
异步架构是典型的生产者-消费者模式,两者不存在直接调用,而是通过缓冲区进行通信,彼此功能实现可以随意变化而不互相影响,这对大大提高了网站的性能与可扩展性。
2.1.2)分布式:空间形式上的解耦
解耦是为了适应网站日益增长的复杂业务需求,解耦之后的下一步则是将切分后的模块分布式部署,即将不同模块部署在不同的服务器上,通过远程调用协同工作,这将进一步提高网站的性能与扩展性。
用户量激增,网站并发成为瓶颈。
I/O多路复用解决了经典的C10K问题(如Nginx,Redis都是典型应用),此时我们不得不将目光从单机投向集群,从集群投向分布式,从分布式投向分布式集群,以寻求更大范围的并发。
相对于单机,集群提升了网站的可伸缩性(指通过不断地向集群中加入服务器的手段来缓解不断上升的用户并发访问压力和不断增长的数据存储需求);分布式(部署)提升了网站的可扩展性(指网站不需要任何改动或者很少改动既有业务功能就可以上线新的业务产品的能力)。在综合了最优网络I/O模型与分布式和集群的优势下,网站的高并发成为可能。
注:解耦在降低系统复杂度的同时也为更好地系统实现高并发创造了条件:分布式场景。
缓存的依据是网站访问数据的特点大体呈现二八定律:80%的业务访问集中在20%的数据上。所以,一旦遭遇网站的数据访问性能问题时,首先想到的就是加缓存。
缓存的世界有这么一句话:有数据的地方就可以有缓存。从这个角度讲,再扩大一点范围:凡是位于速度相差较大的两种介质之间,用于协调两者数据传输差异的结构,均可称为缓存。按照这个概念,只有两种介质之间存在传输速率差,速率较高的一方即可作为较低方的缓存。
在网站的世界,每一层皆可缓存。以PHP应用为例:底层有磁盘文件缓存、CPU缓存;应用层有Zend虚拟机缓存、APC缓存等;数据层有资源文件缓存(CDN)、数据缓存(如Redis/Memcache)等。
2.4)冗余备份:有备无患
实现高可用网站架构的主要手段是:数据和服务的冗余备份及失效转移。有备则无患,如数据库除了定期备份,存档保持,实现冷备份之外,为了保证在线业务高可用,还需要对数据库进行主从分离,实现同步实现热备份。 一旦某些服务器宕机,就将服务切换到其他可用的服务器上,如果磁盘损坏,则从备份的磁盘读取数据。
本文介绍了网站架构中常用的一些方法论与手段,皆是从日常实际工作项目中的积累与沉淀,看上去有点理论有点虚,但十分有指导意义。软件的世界里没有好坏,只有优劣,而架构师追求的永远是业务上的性价比。