在建筑领域是这样描述模式的:每一个模式描述了一个在我们周围不断重复发生的问题以及该问题的解决方案核心。我们可以一次又一次地使用这个方案而不必做重复的工作。模式的关键是可重复性,问题和场景的可重复性带来解决方案的可重复性。
目前的网站架构有一些共同的模式(思路与解决方案),它们已经被大型网站一再验证,所以可以指导我们的架构设计。
1 分层
在横向维度上把系统划分为 3 层,每一层负责相对单一的职责,通过上层对下层的依赖与调用来构成一个完整的系统。
分层 | 描述 |
---|---|
应用层 | 负责具体业务与视图展示。 |
服务层 | 为应用层提供服务支持。 |
数据层 | 提供数据访问服务。 |
只要维持调用的接口不变,各层就可以根据具体问题,独立演化发展。
在设计阶段,必须合理的规划各层之间的边界和接口。在开发阶段,必须严格遵循分层之间的约束,禁止跨层次调用(如应用层调服务层)以及逆向调用(如数据层调应用层)。
在实践中,这些分层还可以进一步细分。比如应用层再分为视图层与业务逻辑层;服务层分为数据接口层与逻辑处理层。
分层架构是逻辑上的划分,所以可以部署在同一台物理服务器上。但随着业务的发展,必须会对这些层进行分离部署,即把这些层分别部署在不同的物理服务器上。
分层架构对于以后支持高并发并朝着分布式方向发展很重要,所以在早期,就应该采用分层架构哦O(∩_∩)O~
2 分割
分割指的是从纵向方面进行划分。
把不同的业务服务包装成高内聚低耦合的模块单元,这样不仅可以有助于开发和维护,也便于实现分布式部署。
3 分布式
分层与分割的目的之一是为了把这些模块进行分布式部署,即把这些模块部署在不同的服务器上,然后通过远程调用协同工作。这就意味着有更多的服务器来提供同样的服务,资源越多,那么支持的并发访问量和数据量就越大,进而可以为更多的用户服务。
但分布式也有一些缺点:
- 必须通过网络调用服务,而这可能会对性能造成严重影响。
- 服务器越多,宕机的可能性就越大,造成可用性降低。
- 保持数据一致性很困难。
- 开发、管理与维护困难。
所以要根据实际情况量力而行哦O(∩_∩)O~
目前有这些分布式方案:
分布式应用与服务 - 可以改善性能和并发性、加快开发与发布速度、减少数据库连接和不同的应用复用共同的服务。
分布式静态资源 - 动静分离,即把 js/css/图片等静态资源部署在独立域名下,这不仅可以加快浏览器的并发加载速度,而且还可以让负责用户体验的团队独立开发与维护这些静态资源,实现分工合作。
分布式数据和存储 - 大型网站需要处理以 P 为单位的海量数据,单台计算机无法提供这么大的存储空间,所以才要分布式存储。像各种 NoSQL 产品几乎都是分布式的。
分布式计算 - 处理在线业务之外,还有很大的一部分是用户直观感受不到的后台业务,诸如构建搜索引擎索引、数据分析统计等。现在普遍使用 Hadoop 和 MapReduce 分布式计算框架进行这一类的批处理计算。它们的特点是移动计算,即把计算程序分发到数据所在的位置以加速计算工作。
4 集群
要对用户访问集中的模块所部署的服务器建立集群,即多台服务器部署相同应用,然后通过负载均衡设备共同对外提供服务。
这样可以提供更好的并发能力,如果因为业务发展有了更多的并发用户的时候,我们只要向集群中增加新机器即可。而且可以提高系统的可用性,所以在早期,也要至少部署两台服务器以构建一个集群,保证可用性。
5 缓存
缓存指的是把数据存放在距离计算最近的位置以加快处理速度,它是改善性能的第一手段。有这些缓存方法:
CDN - 内容分发网络,用户的请求会送达距离他最近的网络服务商,这里缓存了网站的一些静态资源,如果用户的请求是这些资源,那么就可以很快地响应啦O(∩_∩)O~
反向代理 - 是前端架构的一部分,它部署在前端,当用户的请求到达网站时,会最先访问反向代理服务器,这些也缓存了网站的一些静态资源,所以也会很快响应用户的啦O(∩_∩)O~
本地缓存 - 缓存着热点数据,应用程序可以直接从本机内存中读取数据。
分布式缓存 - 如果网站的数据量非常庞大,那么即使只是缓存一小部分,所需要的内存也不是单机能够承受的。为了解决这一问题,我们可以建立分布式缓存集群,应用程序通过网络来访问缓存数据。
使用缓存的前提条件是:
- 数据访问的热点并不均衡,即某些数据会被频繁地访问到,这些数据必须放入内存。
- 数据在某一个时间段内是有效的。如果很快过期,然后缓存数据就会因为失效而出现脏读问题。
6 异步
异步指的是把一个业务分为多个阶段,每个阶段通过共享数据进行协作工作。
单个服务器内可以通过多线程共享内存队列的方式实现异步;而在分布式系统中,多个服务器集群是通过分布式消息队列实现异步的。
异步架构就是典型的生产者/消费者模式。它们不直接调用,只是共享数据结构。
异步消息队列有这些特性:
提高系统可用性 - 消费者服务器发送故障,数据会在消息队列服务器存储堆积,但生产者服务器可以继续处理业务,系统整体表现为正常。待消费者服务器恢复后,就可以继续处理消息处理队列中的数据。
加快响应速度 - 生产者服务器处理完业务请求后,就把数据写入消息队列,无须等待消费者服务器响应即可返回。
消除并发访问高峰 - 消息队列服务器可以吸纳高峰期突然增加的访问请求数据,然后由消费者服务器依次处理,这样不会对整个负载造成太大的压力。
注意:异步方式会对用户体验和业务流程造成影响,所以需要得到产品设计方面的支持。
7 冗余
服务器随时可能出现故障,特别是服务器的规模比较大时,某台服务器出现宕机几乎是必然事件。所以为了保证服务与数据,就必须有一定数量的服务器冗余运行,数据冗余备份,这样当某台服务器宕机时,可以把其上的服务与数据转移到其他机器上。
即使是访问与负载很小的服务,也必须至少部署两台服务器构造一个小的集群,这样才能实现服务的高可用。数据库除了冷备份(定期备份、存档保存)外,还要对数据库进行主从分离,做热备份。
为了防范地震等不可抗力导致服务瘫痪的情况,一些大型网站会对整个数据中心进行备份,在全球范围内部署灾备数据中心。程序与数据会实时同步到多个灾备数据中心。
8 自动化
目前的自动化主要集中在发布与运行维护上。
很多故障都出现在发布环节,所以实现发布自动化可以有效地减少故障。包括这些环节:
- 自动化代码管理 - 开发者只要提交自己代码,系统就会自动为其创建开发分支,自动进行代码合并。
- 自动化测试 - 系统自动把代码部署到测试环境,启动自动化测试用例进行测试,向相关人员发送测试报告,向系统反馈测试结果。
- 自动化安全检测 - 对代码进行静态安全扫描并部署到安全测试环境,进行安全攻击测试,评估系统的安全性。
- 自动化部署 - 把代码自动部署到线上生产环境。
- 自动化监控 - 对服务器进行心跳检测,监控它的各项性能指标和应用程序的关键数据指标。如果发现异常,就进行报警。然后进行失效转移,把失效的服务器从集群中隔离。故障消除后,在进行失效恢复。遇到访问高峰,进行降级,即拒绝部分请求以及关闭一部分不重要的服务。必要时,还需要主动分配资源,把空闲的资源分配给重要的服务。
正确地使用模式,可以用更少的时间开发出更好的系统,而且也使设计者的水平达到一个更高的水平。但要注意:模式受到应用场景的限制,对系统的约束也很多,所以要具体问题具体分析。
只有对问题有着深刻理解的基础上进行创新,才能有好的设计哦O(∩_∩)O~