转太强了!一文讲透了标准Web系统的架构分层~

共 7507字,需浏览 16分钟

 ·

2021-10-24 17:32

上一篇:没想到Sharding-Jdbc竟然这么牛逼!一键实现读写分离、分库分表~

作者:说好不能打脸
来源:https://blog.csdn.net/yinwenjie/article/details/46480485

架构体系分层图
在上图中我们描述了Web系统架构中的组成部分。并且给出了每一层常用的技术组件/服务实现。需要注意以下几点:






负载分配层


实际上负载均衡的概念很广泛,所述的过程是将来源于外部的处理压力通过某种规律/手段分摊到内部各个处理节点上。在日常生活中我们随时随地在和负载技术打交道,例如:上下班高峰期的车流量引导、民航空管局的航空流量管制、银行柜台的叫号系统。

这里我们所说的负载分配层,是单指利用软件实现的计算机系统上的狭义负载均衡。一个大型(日PV一亿+)、中型(日PV一千万+)Web业务系统,是不可能只有一个业务处理服务,而是多台服务器同时进行某一个相同业务的服务。所以我们需要根据业务形态设计一种架构方式,将来自外部客户端的业务请求分担到每一个可用的业务节点上。如下图所示:



负载层还有一个作用,是根据用户的请求规则,将不同的请求类型分派到不同的服务器上。例如:如果某一个HTTP请求是请求一张图片,那么负载层会直接到图片存储介质上寻找相应的图片;如果某一个HTTP请求是提交的一张订单,那么负载层会根据规则将这张订单提交发送到指定的“订单服务”节点上。


不同的业务需求,使用的负载层方案也是不同的,这就考验架构师的方案选择能力。例如Nginx只能处理TCP/IP协议的之上应用层HTTP协议,如果要处理TCP/IP协议,则要按照第三方的TCP-Proxy-Module模。更好的直接在TCP/IP层负载的方案,是使用HAProxy。


常用的负载层架构方式包括: 


- 独立的Nginx负载或HAProxy方案 

- LVS(DR)+ Nginx方案 

- DNS轮询 + LVS + Nginx方案 

- 智能DNS(DNS路由) + LVS + Nginx方案


随后的文章中将详细介绍这些负载架构方案以及这些方案的变形。


业务服务层和通信层


概述


通俗来讲就是我们的核心业务层,订单业务、施工管理业务、诊疗业务、付款业务、日志业务等等。如下图所示:



很明显在中大型系统中,这些业务不可能是独立存在的,一般的设计要求都会涉及到子系统间脱耦:即X1系统除了知晓底层支撑系统的存在外(例如用户权限系统),X1系统不需要知道和它逻辑对等的X2系统的存在就可以工作。这种情况下要完成一个较复杂业务,子系统间调用又是必不可少的:例如A业务在处理成功后,会调用B业务进行执行;A业务在处理失败后,会调用C业务进行执行;又或者A业务和D业务在某种情况下是不可分割的整体,只有同时成功才成功,其中有一个失败整个大的业务过程都失败。如下图所示:

这样一来业务间的通信层又是一个逃不开的话题。在随后的文章中,我们将以Alibaba的Dubbo框架、基于AMQP协议的消息队列和Kafka消息队列技术的原理和使用方式,来讲解业务通信层技术,特别是业务通信层的技术选型注意事项。


不得不提的HTTP请求方式


有的读者可能会问,为什么业务系统间通信层没有提到HTTP这样的调用方式。毕竟很多公司目前都采用这种方式作为业务系统间的调用方式。我们首先通过一个图来看看HTTP方式的调用过程。(注意,此过程不考虑http客户端缓存的过程也不考虑DNS域名解析的过程,从HTTP建立可靠的TCP连接开始):



从上图中我们可以看出以下几个问题:





基于以上的描述,本文并不推荐使用HTTP作为业务间通信/调用的方式,而建议HTTP方式仅限于WEB、iOS、Android等这样的客户端请求服务的方式。


数据存储层


数据存储将是这个系列文章中将要介绍的另一个重点。进行业务计算前的初始数据、计算过程中的临时数据、计算完成后得到的计算结果都需要进行存储。我们通过一张思维导图首先从几个维度阐述一下数据存储的基本分类。

文件存储原理


我们通过一个最基本的在Centos6.5系统上创建Ext4文件系统的过程,讲解文件系统的最基本原理。


首先我们会通过fdisk命令对本地硬盘进行分区(即确定可控制的扇区的范围),如下图所示:



然后我们会在这个区上面通过mkfs命令创建我们想要的文件系统(Ext3、Ext4、LVM、XF、BTRFS等),如下图所示:



最后我们挂载这个文件系统到指定的路径,如下图所示:



通过df命令查看挂载信息,如下图所示: 



万变不离其宗的创建过程告诉我们一个什么事实呢?



物理块,一个物理块是我们上层文件系统能够操作的最小单位(通常为512字节),一个物理块在底层对应了多个物理扇区。通常一块SATA硬盘会有若干机械手臂(决定于物理盘片数量),和若干个物理扇区(物理扇区的大小是磁盘出厂时就确定的,我们无法改变)。


单个扇区的工作是单向的,那么映射出来的一个物理块的工作方式也是单向的。原理就是机械手臂在读取这个扇区的数据时,硬件芯片是不允许机械手臂同时向这个扇区写入数据的。


通过上层文件系统(EXT、NTFS、BTRFS、XF)对下层物理块的封装,OS是不需要直接操作磁盘物理块的,操作者通过ls这样的命令看到的一个一个文件也不需要关心这些文件在物理块的存储格式。这就是为什么不同的文件系统有不同的特性(有的文件系统支持快照,有的文件系统支持数据恢复),基本原理就是这些文件系统对下层物理块的操作规范不一样。


块存储和文件存储


上一小节我们叙述了最简单、最原始的物理块和文件格式规范的工作方式,但是随着服务器端不断扩大的数据存储容量的需求和数据安全性的需求,很显然单机的存储是没办法满足要求的,目前存储环境两种大的需求类型是:


稳定的扩展存储容量,并且不破坏目前已存储的数据信息,不影响整个存储系统的稳定性。


文件共享,让多台服务器能够共享存储数据,并且都可以对文件系统进行读写操作。


要解决这两个问题,我们首先要将问题扩展到上一小节的图例中,如下图所示:



很明显图中两个问题的答案是肯定的,也就是我们将要介绍的块存储系统要解决的问题。


块存储系统


我们先来聊一下块存储。之前我们提到的最简单的情况就是磁盘在本地物理机上,传输的物理块I/O命令,也是通过本地物理机主板上的南桥进行的。但是为了扩展更大的磁盘空间,并且保证数据吞吐量,我们需要将磁盘介质和本地物理机分离,并且让物理块的I/O命令在网络上进行传输:






文件存储系统


那么如果是将文件系统从本地物理机通过网络移植到远程呢?当然可以,典型的文件存储系统包括了FTP、NFS、DAS: 


  • 文件存储系统的关键在于,文件系统并不在本机。而是通过网络访问存在于远程的文件系统,再由远程的文件系统操作块I/O命令完成数据操作。


  • 一般来说诸如本地文件系统NTFS/EXT/LVM/XF等是不允许直接网络访问的,所以一般文件存储系统会进行一层网络协议封装,这就是NFS协议/FTP协议/NAS协议(注意我们说的是协议),再由协议操作文件存储系统的服务器文件系统。


  • 文件存储系统要解决的问题首要的文件共享,网络文件协议可以保证多台客户端共享服务器上的文件结构。从整个架构图上可以看到文件存储系统的数据读写速度、数据吞吐量是没办法和块存储系统相比的(因为这不是文件存储系统要解决的首要问题)。

从上面的简介中我们可以清楚的知晓,当面对大量的数据读写压力的时候,文件存储系统肯定不是我们的首要选择,而当我们需要选择块存储系统时又面临成本和运维的双重压力(SAN系统的搭建是比较复杂的,并且设备费用昂贵)。并且在实际生产环境中我们经常遇到数据读取压力大,且需要共享文件信息的场景。那么这个问题怎么解决呢?


对象存储系统


兼具块存储系统的高吞吐量、高稳定性和文件存储的网络共享性、廉价性的对象存储就是为了满足这样的需求出现的。典型的对象存储系统包括:MFS、Swift、Ceph、Ozone等。下面我们简单介绍一下对象存储系统的特点,在后面的文章中,我们将选择一款对象存储系统进行详细说明。


对象存储系统一定是分布式文件系统。但分布式文件系统不一定是对象存储系统






数据库存储


这篇文章已经写了很多存储层的概要描述了,所以我们熟悉或者不熟悉的数据库存储技术的概述就不在这里介绍了。


后续的文章我将使用Mysql讲解几个常用的架构方案和性能优化点,当然也会讲到Mysql中,诸如Innodb这样的核心数据引擎的工作方式。这些架构方案主要解决的是Mysql的单机I/O瓶颈、机房内数据容灾、数据库稳定性、跨机房数据容灾等核心问题。


后续的文章我还会选取目前流行的数据缓存系统,讲解其工作原理、核心算法和架构方案。以便读者们根据自己的业务情况设计符合业务的存储集群。当然还有非关系型数据库Cassandra、HBase、MongoDB的深入介绍。


评价架构的特性


我们如何来评价一个服务系统的顶层设计是否优秀呢?抛开八股文式的扩展性、稳定性、健壮性、安全性这样的套话不说。我从实际工作中为大家总结了一下几个评价要点。


建设成本


任何系统架构在进行生产环境实施的时候,都是需要付出建设成本的。显然各个公司/组织对成本的承受度是不一样的(这些成本包括:设计成本、资产采购成本、运维成本、第三方服务成本),所以如何利用有限的成本建设出符合业务需求、适应访问规模的系统,就是一个复杂的问题。另外,这种要求下架构师是不能进行过度设计的。


扩展/规划水平


根据业务的发展,整个系统是需要进行升级的(这包括已有模块的功能升级、合并已有的模块、加入新的业务模块或者在模块功能不变的情况下提高数据吞吐量)。那么如何尽量不影响原业务的工作,以最快的速度、最小的工作量来进行系统的横向、纵向扩展,也就是一个复杂的问题了。好的系统架构是可以在用户无任何感觉的情况下进行升级的,或者只需要在某些关键子系统升级时才需要短暂的停止服务。


抗攻击水平


对系统的攻击肯定是瞄准整个系统最薄弱的环节进行的,攻击可能来自于外部(例如Dos/DDos攻击)也可能来自于内部(口令入侵)。好架构的系统不是“绝对不能攻破”的系统,而是“预防很好”的系统。所谓预防,就是预防可能的攻击,分阶段对可能遇到的各种攻击进行模拟;所谓隐藏,就是利用各种手段对整个系统的关键信息进行涉密管理,ROOT权限、物理位置、防火墙参数、用户身份。


容灾恢复等级


好的架构应该考虑不同等级的容灾。集群容灾,在集群中某一个服务节点崩溃的情况下,集群中另外一台主机能够接替马上接替他的工作,并且故障节点能够脱离;分布式容灾:分布式系统一般会假设整个系统中随时都在发生单点故障/多点故障,当产生单点故障/多点故障时,整个分布式系统都还可以正常对外提供服务,并且分布式系统中的单点故障/多点故障区可以通过自动/人工的方式进行恢复,分布式系统会重新接纳它们;异地容灾(机房等级容灾):在机房产生物理灾难的情况下(物理网络断裂、战争摧毁、地震等),在某个相隔较远的异地,备份系统能够发现这样的灾难发生,并主动接过系统运行权,通知系统运维人员(根据系统不同的运行要求,可能还有多个备份系统)。异地容灾最大的挑战性是如何保证异地数据的完整性。


业务适应性水平


系统架构归根结底还是为业务服务的,系统架构的设计选型一定是以服务当前的业务为前提。在上文中提到的业务通信层中,选择SOA组件还是消息队列组件,又或者选择什么样的消息队列,就是一个很好的业务驱动事件。例如,A业务是一种WEB前端服务,需要及时反馈给客户操作结果,B业务的服务压力又非常大。A业务在调用B业务时,B业务无法在毫秒级的时间内返回给A业务调用结果。这种业务场景下可以使用AMQP类型的消息队列服务。另外说明两点,目前行业内有很多为解决相同业务场景存在的不同方案,架构师在进行方案选型的过程中,一定要对各种解决方案的特点足够掌握,这样才能做出正确的选择;另外行业内的解决方案已经足够多,架构师在业务没有特殊要求的情况下一定不要做“ 重复发明轮子”的事情。


维护难易程度


一套服务系统从架设之初就需要运维团队不断的进行投入。显然根据系统的复杂程度和物理机器的数量,运维团队的知识复杂性也是不一样的。在架构师进行顶层架构设计时,必须还要考虑系统的运维难度和运维成本。


其他说明




感谢您的阅读,也欢迎您发表关于这篇文章的任何建议,关注我,技术不迷茫!小编到你上高速。

    · END ·
最后,关注公众号互联网架构师,在后台回复:2T,可以获取我整理的 Java 系列面试题和答案,非常齐全


正文结束


推荐阅读 ↓↓↓

1.不认命,从10年流水线工人,到谷歌上班的程序媛,一位湖南妹子的励志故事

2.如何才能成为优秀的架构师?

3.从零开始搭建创业公司后台技术栈

4.程序员一般可以从什么平台接私活?

5.37岁程序员被裁,120天没找到工作,无奈去小公司,结果懵了...

6.IntelliJ IDEA 2019.3 首个最新访问版本发布,新特性抢先看

7.这封“领导痛批95后下属”的邮件,句句扎心!

8.15张图看懂瞎忙和高效的区别!


浏览 20
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报