与传统企业应用系统相比,大型互联网应用系统有以下特点。
分层是企业应用系统中最常见的一种架构模式,将系统在横向维度(还会讲到纵向维度,注意之间的区别)上切分成几个部分,每个部分负责一部分比较单一的职责,然后通过上层对下层的依赖和调用组成一个完整的系统。
如:网络的7层通信协议、MVC的架构都是一种分层结构
大型网站中也采用分层结构,将网站大致分为:应用层、服务层、数据层,如下表所示:
应用层 | 负责具体业务和视图展示,如:网站首页及搜索输入和结果的展示 |
服务层 | 为应用层提供服务支持,如:用户管理服务,购物车服务等 |
数据层 |
提供数据存储访问服务,如:数据库、缓存、文件、搜索引擎等 |
但在实践中,大的分层结构内部还可以继续分层,如:应用层可以分为视图层(美工/前端负责)和业务逻辑层(后台工程师负责) ;服务层可以分为逻辑处理层和数据接口层(适配各种输入和输出的数据格式)
建议:虽然分层架构模式最初的目的是规划软件清晰的逻辑结构便于开发维护,但在网站的发展过程中,分层结构对网站支持高并发分布式方向发展至关重要,因此在网站发展之初就应该采用分层的架构,这样将来网站做大时才能有更好地应对。
如果说分层是将软件在横向维度进行切分,那么分割就是在纵向维度(可以理解为:功能/服务模块化)对软件进行切分。
网站越大,功能越复杂,服务和数据处理的种类也越多,将这些不同的功能和服务分割开来,包装成高内聚低耦合的模块单元,一方面有助于软件的开发和维护;另一方面,便于不同模块的分布式部署,提高网站的并发处理能力和功能扩展能力。
如:在应用层,将不同业务进行分割,将购物、论坛分割成不同的引用,由独立的团队负责,部署在不同的服务器上;
购物业务,可以进一步分割为机票酒店业务、小商品业务等
对于大型网站,分层和分割的一个主要目的是为了切分后的模块便于分布式部署,即:将不同模块部署在不同的服务器上,通过远程调用协同工作。分布式意味着一个模块可利用的CPU、内存、内存资源也就越多,能够处理的并发访问和数据量就越大,进而能够为更多的用户提供服务。
但分布式在解决网站高并发问题的同事也带来了其他问题。列举如下:
在网站应用中,常用的分布式方案有以下几种:
此外,还有可以支持网站线上服务器配置实时更新的分布式配置;分布式环境下实现并发和协同的分布式锁;支持云存储的分布式文件系统等。
使用分布式虽然已经将分层和分割后的模块独立不是,但是对于用户访问几种的模块(如:网站的首页),还需要将独立部署的服务器集群化,即:多台服务器部署相同应用构成一个集群,通过负载均衡设备共同对外提供服务。(可以说集群是建立在分布式基础上的,分布式满足不了,向外扩展集群模式)。
因为服务器集群有更多服务器提供相同服务,因此可以提供更好的并发特性,当有更多用户访问的时候,只需要向集群中加入新的机器即可。同时因为一个应用由多台服务器提供(集群核心体现),当某台服务器发生故障时,负载均衡设备或者系统的失效转移机制会将请求转发到集群中其他服务器上,使服务器故障不影响用户使用。
所以:在网站应用中,即使是访问量很小的分布式应用和服务,也至少要部署两台服务器构成一个小的集群,目的就是提高系统的可用性。
缓存就是将数据存放在距离计算最近的位置以加快处理速度并减轻应用服务和数据库服务器的负载压力。缓存是改善软件性能的第一手段。
使用缓存有两个前提条件:
大型网站架构设计在很多方面都使用了缓存设计。
CDN:即内容分发网络,CDN部署在距离终端用户最近的网络服务商,用户的网络请求总是先到达他的网络服务商那里。在这里缓存网站的一些静态资源(较少变化的数据),可以就近以最快的速度返回给用户,如:视频网站和门户网站会将用户访问量大的热点内容缓存在CDN。
反向代理:反向代理属于网站前端架构的一部分,反向代理部署在网站的前端,当用户请求到达网站的数据中心时,最先访问到的就是反向代理服务器,这里缓存网站的静态资源,无需将请求继续转发到应用服务器就能返回给用户。
本地缓存:在应用服务器本地缓存着热点数据,应用程序可在本机内存中直接访问数据,而不需访问数据库。
分布式缓存:大型网站的数据量非常庞大,即使只缓存一小部分,不要的内存空间也不是单机能承受的,所以除了本地缓存,还需要分布式缓存,将数据缓存在一个专门的分布式缓存集群中,应用程序通过网络通信访问缓存数据。
计算机软件发展的一个重要目标和驱动力是降低软件耦合性。事物之间直接关系越少,就越少被彼此影响,越可以独立发展。大型网站架构中,系统解耦合的手段除了前面提到的分层、分割、分布式等,还有一个重要手段是异步,业务之间的消息传递不是同步调佣,而是一个业务操作分成多个阶段,每个阶段之间通过共享数据的方式异步执行进行协作。
在单一服务器内部可通过多线程共享内存队列的方式实现异步,处在业务操作前面的线程将输出写入到队列,后面的线程从队列中读取数据进行处理;
在分布式系统中,多个服务器集群通过分布式消息队列实现异步,分布式消息队列可以看做内存队列的分布式部署。
异步架构是典型的生产者消费者模式,两者不存在直接调用,只要保持数据结构不变,彼此功能实现可以随意变化而不互相影响,这对网络扩展新功能非常便利。除此之外,使用异常消息队列还有如下特性:
网站需要7*24小时连续运行,但是服务器随时可能出现故障,特别是服务器规模比较大时,出现某台服务器宕机是必然事件。要想保证在服务器宕机的情况下网站依然可以继续服务,不丢失数据,就需要一定程度的服务器冗余运行,数据冗余备份,这样当某台服务器宕机时,可以将其上的服务和数据访问转移到其他机器上。
访问和负载很小的服务也必须部署至少两台服务器构成一个集群,其目的是通过冗余实现服务高可用。
数据库除了定期备份,存档保存,实现冷备份外,为了保证在线业务高可用,还需对数据库进行主从分离,实时同步实现热备份。
自动化一般有:
互联网的开放特性使得其从诞生起就面对巨大的安全挑战,网站在安全架构方面也积累了许多模式:
一般来说,除了当前的系统功能需求外,软件架构还需要关注性能、可用性、伸缩性、扩展性和安全性这5个架构要素,架构设计过程中需要平衡这5个要素之间的关系以实现需求和架构目标,也可以通过考虑这些架构要素来衡量一个软件架构设计的优劣,判断其是否满足期望。
性能问题无处不在,优化网站性能的手段也非常多,从用户浏览器到数据库,影响用户请求的所有环节都可以进行性能优化。
在浏览器端:
可以通过浏览器缓存、使用页面压缩、合理布局页面、减少Cookie传输等手段改善性能。
架构层面:
使用CDN:将网站静态内容分发至离用户最近的网络服务商机房,使用户通过最短访问路径获取数据。
使用反向代理:可以在网站机房部署反向代理服务器,缓存热点文件,加快请求响应速度,减轻应用服务器负载压力。
使用本地缓存和分布式缓存:在应用服务器端,可以使用服务器本地缓存和分布式缓存,通过缓存在内存中的热点数据处理用户请求,加快请求处理过程,减轻数据库负载压力。
使用异步:通过异步操作将用户请求发送至消息队列等待后续任务处理,而当前请求直接返回响应给用户。
使用集群:在网站有很多高并发请求的情况下,可以将多台应用服务器组成一个集群共同对外服务,提高整体处理能力,改善性能。
代码层面:
通过使用多线程、改善内存管理等手段优化性能。
在数据库服务器端:
使用索引、缓存、SQL优化等性能手段。另外NoSQL数据库通过优化数据模型、存储结构、伸缩特性等手段在性能的优势也日趋明显。
衡量网站性能有一系列指标,重要的有响应时间、TPS、系统性能计数器等,通过测试这些指标以确定系统设计是否达到目标。
几乎所有的网站都承诺7*24可用,但事实上任何网站都不可能达到完全的7*24可用,总会有一些故障时间,扣除这些故障时间,就是网站的总可用时间,这个时间可用换算成网站的可用性指标,以此衡量网站的可用性。
网站高可用的主要手段是冗余,应用部署在多台服务器上同时提供访问,数据存储在多台服务器上互相备份,任何一台服务器宕机都不会影响应用的整体可用,也不会导致数据丢失。
对于应用服务器而言,多台应用服务器通过负载均衡设备组成一个集群共同对外提供服务,任何一台服务器宕机,只需把请求切换到其他服务器就可实现应用的高可用,但是一个前提条件是应用服务器上不能保存请求的会话信息。否则服务器宕机,会话丢失,即使将用户请求转发到其他服务器上也无法完成业务处理。
对于存储服务器,由于其上存储着数据,需要对数据进行实时备份,当服务器宕机时需要将数据访问转移到可用的服务器上,并进行数据恢复以保证继续有服务器宕机的时候数据依然可用。
衡量架构伸缩性的主要标准就是是否可以用多台服务器构建集群,是否容易向集群中添加新的服务器;加入新的服务器后是否可以提供和原来的服务器无差别的服务;集群中可容纳的总的服务器数量是否有限制。
对于应用服务器集群,只要服务器上不保存数据,所有服务器都是对等的,通过使用合适的负载均衡设备就可以向集群中不断加入服务器。
对于缓存服务器集群,加入新的服务器可能到会缓存路由失效,进而导致集群中大部分缓存数据都无法访问。虽然缓存的数据可通过数据库重新加载,但是如果应用已经严重依赖缓存,可能会导致整个网站崩溃。需要改进缓存路由算法保证缓存数据的可访问性(可以使用Hash一致性算法https://blog.csdn.net/cb_lcl/article/details/81448570)。
关系数据库虽然支持数据复制,主从热备等机制,但是很难做到大规模集群的可伸缩性,因此关系数据库的集群伸缩性方案必须在数据库之外实现,通过路由分区等手段将部署有多个数据库的服务器组成一个集群。
大部分NoSQL(非关系数据库)数据库产品,由于其先天就是为海量数据而生,因此其对伸缩性的支持通常都非常好,可以做到在较少运维参与的情况下实现集群规模的线性伸缩。
不同于其他架构要素主要关注非功能性需求,网站的扩展性架构直接关注网站的功能需求。网站快速发展,功能不断扩展,如果涉及网站的架构使其能够快速响应需求变化,是网站可扩展架构主要的目的。
衡量网站架构扩展性好坏的主要标准就是在网站增加新的业务产品时,是否可以实现对现有产品透明无影响,不需要任何改动或者很少改动既有业务功能就可以上线新产品。不同产品之间是否很少耦合,一个产品改动对其他产品无影响,其他产品和功能不需要受牵连进行改动。
网站可扩展架构的主要手段是事件驱动架构和分布式服务。
事件驱动架构在网站通常利用消息队列实现,将用户请求和其他业务事件构造成消息发布到消息队列,消息的处理者作为消费者从消息队列中获取消息进行处理。通过这种方式将消息产生和消息处理分离开来,可以透明地增加新的消息生产者任务或者新的消费者任务。
分布式服务则是将业务和可复用服务分离开来,通过分布式服务框架调用。新增产品可以通过调用可复用的服务实现自身的业务逻辑,而对现有产品没有任何影响。可复用服务升级变更的时候,也可以通过提供多版本服务对应用实现透明升级,不需要强制应用同步变更。
衡量网站安全架构的标准就是针对现存和潜在的各种攻击与窃密手段,是否有可靠的应对策略。