架构模式对比
分层模式
一般信息系统中最常见的4层划分如下:
- Presentation layer 表示层(也就是UI层)
- Application layer 应用层(也就是服务层)
- Business logic layer 业务逻辑层(也就是领域层)
- Data access layer 数据访问层(也就是数据持久层)
应用:一般桌面应用程序,电子商务WEB应用程序
CS客户端-服务器模式
客户端向服务器发起请求,服务器向这些客户端提供相关服务,之后,服务器继续侦听客户端的请求
应用:电子邮件、文件共享、银行业务
主从模式
主模块在相同的从模块之间分配工作,并根据从模块返回的结构来计算最终的结果
应用:在数据库复制中,主数据库被视作权威数据源,而从数据库与其保持同步
连接到计算机系统总线上的外围设备(主驱动器和从驱动器)
管道过滤模式
构建产生和处理数据流的系统。每个处理步骤都包含在一个过滤器组件中,要处理的数据通过管道传递。这些管道可用于缓冲或者同步
应用:
编译器,依次使用不同的过滤器执行词法分析、解析、语法分析和代码生成
生物信息学中的工作流程
Broker模式
使用解耦的组件构建分布式系统,这些组件可以通过远程服务调用实现交互。代理组件负责协调组件之间的通信
服务器将它们的功能(服务和特征等)发布到代理,客户端向代理请求服务,然后代理根据其注册表将客户端请求转发给合适的服务
应用:
消息代理软件,如 Apache ActiveMQ, Apache Kafka, RabbitMQ 和 JBoss Messaging.
P2P模式
每个独立的组件被称为对等点(或对等端,peer)。对等端既可以充当客户端(向其它对等端请求服务),又可以充当服务器(向其它对等方提供服务)
同一个对等端可能既是客户端,又是服务器,并且可以动态改变其角色
应用:
文件共享网络,如Gnutella 和 G2
多媒体协议,如P2PTV 和 PDTP
基于加密货币的产品,如比特币和区块链
事物总线模式
该模式主要处理组件,有4个重要的组件:事件源、事件侦听器、通道和事件总线。事件源将消息发送到事件总线上的特定通道,侦听器会订阅特定的频道。当消息发送到频道中后,订阅该频道的侦听器会收到该消息的通知
应用:
安卓开发
通知服务
MVC模式
该模式将交互式应用分为三个部分,为了将数据的内部表示与用户输入和向用户展示的形式分离开来,这样可以解耦组件,同时也可以进行高效的代码重用
模型——包含核心功能和数据
视图——向用户显示信息(可以定义多个视图)
控制器——处理用户的输入
应用:
主流编程语言的互联网应用架构
网络框架,如Django 和 Rails
黑板模式
此模式对于尚无确定性解决方案的问题很有用,黑板模式由三部分组成:
所有组件都可以访问黑板,组件可能会产生要添加到黑板中的新数据对象,组件在黑板上寻找特定类型的数据,并且可以通过与现有知识源进行模式匹配来找到这些数据。
黑板—— 一个结构化的全局内存,包含解决方案领域的对象
知识源——具有自身含义的专业模块
控制组件——选择、配置和执行模块
应用:
语音识别
车辆识别与跟踪
蛋白质结构鉴定
声呐信号解释
解释器模式
此模式通常用于设计组件来解释使用专用语言写出的程序,它主要指定如何估算程序行,即以特定语言编写的语句或表达式
应用
数据库查询语言,如SQL
用于描述通信协议的语言
====================================================================
单体架构
前端(Web/手机端)+中间业务逻辑层+数据库层
分布式应用
是单体架构的并发扩展,将一个大的系统划分为多个业务模块,业务模块分别部署在不同的服务器上,各个业务模块之间通过接口进行数据交互。数据库也大量采用分布式数据库,如redis、ES、solor等。
通过LVS/Nginx代理应用,将用户请求均衡的负载到不同的服务器上。
微服务架构
Serverless架构
云计算战场:Serverless架构
架构图
场景视图、逻辑视图、物理视图、处理流程视图和开发视图
场景视图
用于描述系统的参与者与功能用例间的关系,反映系统的最终需求和交互设计,通常由用例图表示
逻辑视图
用于描述系统软件功能拆解后的组件关系,组件约束和边界,反映系统整体组成与系 统如何构建的过程,通常由UML的组件图和类图来表示
物理视图
描述系统软件到物理硬件的映射关系,反映出系统的组件是如何部署到一组可 计算机器节点上,用于指导软件系统的部署实施过程
处理流程视图
用于描述系统软件组件之间的通信时序,数据的输入输出,反映系统的功能流程 与数据流程,通常由时序图和流程图表示
开发视图
描述系统的模块划分和组成,以及细化到内部包的组成设计,服务于开发人员,反映系统开发实施过程
C4建模工具
1、语境图(System Context Diagram)
2、容器图(Container Diagram)
3、组件图(Component Diagram)
4、类图(Code/Class Diagram)
设计模式
一、单库单应用设计模式
这种模式一般只有一个数据库,一个业务应用层,一个后台管理系统,所有的业务都是用过业务层完成的,所有的数据也都是存储在一个数据库中的,好一点会有数据库的同步。
优点:结构简单、开发速度快、实现简单,可用于产品的第一版等有原型验证需求、用户少的设计。
缺点:性能差、基本没有高可用、扩展性差,不适用于大规模部署、应用等生产环境。
二、内容分发设计模式
所有的大型的网站都有或多或少的采用这一种设计模式,常见的应用场景是使用CDN技术把网页、图片、CSS、JS等这些静态资源分发到离用户最近的服务器。
这种模式较单库单应用模式多了一个CDN、一个云存储OSS(七牛、又拍等雷同)。一个典型的应用流程(以用户上传、查看图片需求为例)如下:
- 上传的时候,用户选择本地机器上的一个图片进行上传
- 程序会把这个图片上传到云存储OSS上,并返回该图片的一个URL
- 程序把这个URL字符串存储在业务数据库中,上传完成。
- 查看的时候,程序从业务数据库得到该图片的URL
- 程序通过DNS查询这个URL的图片服务器
- 智能DNS会解析这个URL,得到与用户最近的服务器(或集群)的地址A
- 然后把服务器A上的图片返回给程序
- 程序显示该图片,查看完成。
这个模式的关键是智能DNS,它能够解析出离用户最近的服务器。运行原理大致是:根据请求者的IP得到请求地点B,然后通过计算或者配置得到与B最近或通讯时间最短的服务器C,然后把C的IP地址返回给请求者。
优点:资源下载快、无需过多的开发与配置,同时也减轻了后端服务器对资源的存储压力,减少带宽的使用。
缺点:目前来说OSS,CDN的价格还是稍微有些贵(虽然已经降价好几次了),只适用于中小规模的应用,另外由于网络传输的延迟、CDN的同步策略等,会有一些一致性、更新慢方面的问题
三、查询分离模式
这种模式主要解决单机数据库压力过大,从而导致业务缓慢甚至超时,查询响应时间变长的问题,也包括需要大量数据库服务器计算资源的查询请求。这个可以说是单库单应用模式的升级版本,也是技术架构迭代演进过程中的必经之路。
这种模式较单库单应用模式与内容分发模式多了几个部分,一个是业务数据库的主从分离,一个是引入了ES
四、微服务模式
如下的问题:
- 单机数据库写请求量大量增加,导致数据库压力变大
- 数据库一旦挂了,那么整个业务都挂了
- 业务代码越来越多,都在一个GIT里,越来越难以维护
- 代码腐化严重、臭味越来越浓
- 上线越来越频繁,经常是一个小功能的修改,就要整个大项目要重新编译
- 部门越来越多,该哪个部门改动大项目中的哪个东西,撕逼的厉害
- 其他一些外围系统直接连接数据库,导致一旦数据库结构发生变化,所有的相关系统都要通知,甚至对修改不敏感的系统也要通知
- 每个应用服务器需要开通所有的权限、网络、FTP、各种各样的,因为每个服务器部署的应用都是一样的
- 作为架构师,我已经失去了对这个系统的把控…
业务分块,做了垂直切分,切成一个个独立的系统,每个系统各自衍化,有自己的库、缓存、ES等辅助系统,系统之间的实时交互通过RPC,异步交互通过MQ,通过这种组合,共同完成整个系统功能。
优点:相对高性能,可扩展性强,高可用,适合于中等以上规模公司架构。
缺点:复杂、度不好把握。指不仅需要一个能在高层把控大方向、大流程、总体技术的人,还需要能够针对各个子系统有针对性的开发。把握不好度或者滥用的话,这个模式适得其反!
五、多级缓存模式
应对超高查询压力的一种普遍采用的策略,基本的思想就是在所有链路的地方,能加缓存就加缓存
如下图所示,一般在三个地方加入缓存,一个是客户端处,一个是API网关处,一个是具体的后端业务处
- 客户端处缓存,无延迟,不用经过长长的网络链条去后端业务处获取数据,所以提高性能
- API网关处缓存,不用把请求发送给后方,直接在此处理,然后返回给请求者。http请求、API网关用的nginx,可以使用nginx本身的缓存模块,也可以用Lua+Redis技术定制化
- 后端业务处缓存,Redis,Memcache,JVM等
六、分库分表模式
主要解决单表写入、读取、存储压力过大,从而导致业务缓慢甚至超时,交易失败,容量不够的问题。
一般有水平切分和垂直切分两种,这里主要介绍水平切分。把一张表分到了几个不同的库中,从而分担压力。
- 主机,硬件,一台物理机(或虚拟机)
- 实例,数据库实例,如一个MySQL服务进程,一个主机可以有多个实例,不同的实例有不同的进程,监听不同额端口
- 库,表的集合
- 表,库中的表
如何单表分散:
- 主机,由物理机,主机提供的
- 实例,实例控制着连接数,同时受OS限制,CPU、内存、硬盘、网络IO也会受间接影响。
- 库,一般是由于单库中最大单表数量的限制,才采取分库。
- 表,单表压力过大,索引量大,容量大,单表的锁。据以上,把单表水平切分成不同的表。
大型应用中,都是一台主机上只有一个实例,一个实例中只有一个库,库实例主机,所以才有了分库分表这个简称。
单表数据量1亿,查询、插入、存储都出现了问题:
- 可以分为10个库,这样每个库的数据量就降到了1KW
- 单表1KW数据量还是有些大,而且不利于以后量的增长,所以每个库再分100个表,这个每个单表数据量就为10W了
- 对于查询、索引更新、单表文件大小、打开速度,都有一些益处。接下来,给IT部门打电话,要10台物理机,扩展数据库…
- 首先是写入数据,需要知道写到哪个分库分表中,读也是一样的,所以,需要有个请求路由层,负责把请求分发、转换到不同的库表中,一般有路由规则的概念。
优点:减少数据库单表的压力。
缺点:事务保证困难、业务逻辑需要做大量改造。
七、弹性伸缩模式
解决突发流量的到来,导致无法横向扩展或者横向扩展太慢,进而影响业务,全站崩溃的问题。
如下图所示,多了以恶弹性伸缩服务,用来动态的增加、减少实例。
双十一、六一八,人工扩容、缩容。
为此,首先把所有的计算资源整合成资源池的概念,然后通过一些策略、监控、服务,动态的从资源池中获取资源,用完后在放回到池子中,供其他系统使用。具体实现上比较成熟的两种资源池方案是VM、docker,每个都有着自己强大的生态。监控的点有CPU、内存、硬盘、网络IO、服务质量等,根据这些,在配合一些预留、扩张、收缩策略,就可以简单的实现自动伸缩。
八、多机房模式
主要解决不同地区高性能、高可用的问题
应用用户不断的增加,用户群体分布在全球各地,如果把服务器部署在一个地方,一个机房,比如北京,那么美国的用户使用应用的时候就会特别慢,因为每一个请求都需要通过海底光缆走上个那么一秒钟(预估)左右,这样对用户体验及其不好。怎么办?使用多机房部署。
用户请求一个链接A 通过DNS智能解析到离用户最近的机房B 使用B机房服务链接A
数据同步问题,在中国产生的数据要同步到美国,美国的也一样,数据同步就会涉及数据版本、一致性、更新丢弃、删除等问题。其次是一地多机房的请求路由问题,典型的是如上图,中国的北京机房和杭州机房,如果北京机房挂了,那么要能够通过路由把所有发往北京机房的请求转发到杭州机房。异地也存在这个问题。