分层架构模式
什么是分层架构?
层:软件的逻辑单元
每一层有特定的功能
组件被分配到不同的层
为什么分层?
将系统按照职责拆分和组织
上层依赖于直接下层,下层不可以依赖上层
不可以跃层访问
(经典分层架构:OSI 7层架构:应用层 表示层 会话层 传输层 网络层 数据链路层 物理层。CS 、BS 架构,企业应用三层架构)
缘何分层
康威定律:系统的架构受制于组织的沟通结构
复杂度隔离:隔离业务复杂度和技术复杂度、解决不同层的问题可以选择不同技术栈、
每层变化速度不一致
防止错误传播
减低错误影响
防水仓设计
层自治:本层功能内聚、自主决策、只有本层的知识
分层架构优点
高内聚
低耦合
可维护性好
可测试性高
分层架构缺点
性能下降:分层引入通信开销、层与层都有数据转化、不能跨层访问
开发成本上升
分层架构设计
依赖规则
越向外越具体,越朝内越抽象
外圈 是软件,内圈是规则
依赖关系只能从外向内
定义职责
高层表示规则,底层实现细节
逻辑内聚自治分组
依据组织职责分工
定义技术栈
根据每层的需求各自选定
借鉴成功案例 ↵
部署方式
代码抽象与分层
层对外暴露接口,隐藏实现细节
实现依赖于抽象,抽象不可依赖于实现细节
代码不跨层调用,只依赖于直接的下一层
集成
集成前做单元测试
根据接口和技术栈确定集成方式
集成联调
分层架构模型
MVC
Model:Domain model 和业务逻辑
View: 展示数据和用户交互
Controller:接收输入并转换为对mode的操作
将model转化为view能展示的数据
MVVM
BFF
Backend for frontend
避免了终端与多个服务的交流
GraphQL
面试指导:
Http和底层TCP IP链接的关系
什么MVC架构?采用何种技术实现mvc
Spring Cloud Hystrix 断路器的工作原理
如何完成legacy系统重构
事件驱动的架构模式
什么是 EDA
事件驱动架构模式是一种异步分发事件的架构模式
用于高扩展且低耦合的系统
事件为核心,一系列解耦的、单一功能的事件处理器
两种Topology
Mediactor 中介 流程
Broker 无中心 无流程
Mediator中介模式
存在业务流程
多步骤
统一协调,居中调度
事件分层次
Event queue
源系统将event发送到queue
event 处理系统从queue中消费event
源系统和事件处理系统的连接点
Queue只关心事件的传输
Event mediator
中介从queue中消费原始事件,并分配、协调各个执行步骤
对应业务处理的各个步骤,产生待处理事件(业务事件)
将待处理事件异步分发带不同的通道(channel)
无具体业务逻辑,只知道有哪些步骤
Event channel
Mediator向channel发送消息processor从channel读取
某种业务事件(消息)的聚合
多个processor可以监听同一个channel
Event processor
监听channel的event
具体的、单一功能的业务逻辑单元
处理器之间无关联性
Mediator模式应用场景
Broker代理模式
无中心控制器
轻量的消息代理将消息串联成链状
分发至事件处理器组件
事件处理器独立运作
Event channel
Event Processor
监听channel的event,判断是否处理
处理一个事件,并发送一个事件,标明其行为
事件处理器,单一业务逻辑
处理器无关联性,不构成业务逻辑链
Broker
轻量级的代理
无业务逻辑的简单消息分发
源系统将event发送至代理(通道)共processor消费
事件通道可以是queue,topic或者两者组合
Broker模式应用场景:订单状态日志记录
Notification
源系统发送消息通知其他系统状态改变
接收方响应非必须
发身Event逻辑与处理Event逻辑无依赖,独立变化
解耦,各自扩展
Carried State Transfer
源系统推送信息及变化
依赖者生成信息副本
容错
源系统不可用时,依赖者可以使用副本
依赖者维护信息副本和变化
数据的冗余
数据一致性
提高整体性能
依赖者直接使用信息副本
EDA解决了什么问题
EDA优点
整体灵活性
架构能否在不断改变的使用场景下快速响应
事件处理器组件目的单一、高度解耦,可以独立变化
代理拓扑结构比中介拓扑结构调度会更容易
事件中介与事件处理器是耦合的
代理模式完全耦合
可扩展性
高度解耦,独立变化
横向扩展
不同组件的运行节点数均可自行调整
组件本身可以自行决定是否再拆分实现
纵向扩展
计算密集型还是内存密集型,按需调整
性能
细粒度的事件处理器有利于提高性能
整体架构是异步并行有利于提高性能
易于部署
高度解耦的事件处理器组件让整体部署相对容易
缺点
可测试性
单元测试无差异
集成测试难
组件众多
异步
可维护性
分布式部署
异步
异常处理难
性能
分布式消息传递会降低性能
典型应用场景
NIO
针对不同的IO event分配不同的handler
Selector : 监控哪些Channel 有IO event
SelectionKey:维护IO event的状态和绑定的handler
Nginx
Nginx的工作进程一直监听端口并等待Event
Event 是由新建立的连接所触发
所有的连接都会被分配到一个对应的状态机
Non-blocking
短信验证码
电商订单生命周期管理
数据同步消息广播
模拟面试
servlet规范中listener的工作原理
电商系统下单成功,如果有风控问题,需要客服介入,如何设计
淘汰老系统,如何实现双写
微内核架构(可扩展)模式
定义
系统核心
资源封装
硬件接口
系统资源访问接口
环境/上下文访问接口
系统事件接口
定义插件规范
使用场景
规则
条件
核心功能
支持系统运作的最小功能集
职责分离
通用流程由核心系统定义
核心定义规范,插件具体实现
插件模块
核心系统能力扩展
遵循核心系统规范
实现其逻辑外延和业务逻辑
Single Responsibility
专注于其独立功能
只能通过核心提供的接口操作系统资源
插件间无依赖
尽可能避免依赖其他插件
只依赖于核心
隔离
插件不能影响核心
注册
插件可用性
获取插件的方式
插件信息抽象规范
名称、数据规范、访问协议
连接
自定义连接方式
OSGI,点对点绑定(依赖注入)
web service,message
通信规范
标准规范配合版本策略
自定义规范配合Adapter
事件
点对点 | 发布/订阅 | |
全局事件 | 是 | 否 |
系统事件 | 否 | 是 |
插件事件 | 否 | 是 |
优点
符合开闭原则
核心系统封闭
插件提供开放性
整体系统可持续升级
良好的隔离性
核心系统可以关闭插件
错误的传播范围有限
插件内的错误不会被转播到核心系统
各自独立升级改进
可能有兼容性问题
灵活性
核心系统保持稳定,将变化尽量隔离在插件层
插件根据核心提供的接口和规范来提供丰富的功能
整体保持开放,持续进化
可测试性
核心系统和插件系统可以分开测试
插件可以运行在模拟环境
性能
通过简化核心系统,提高性能
插件按需加载,降低资源消耗
可以动态关闭插件以保护核心系统
易于部署
插件在运行时动态添加到核心系统
减少核心系统停机时间
缺点
开发难度高
需要分离核心功能与插件功能
插件需要热插拔
需要专门注册协议和通信协议
可扩展性不高
主要用于开发产品,不考虑扩展性
不以可扩展性见长
可以结合其他模式获得扩展性
使用微内核
实际系统核心
定义核心功能
实现MVP
封装系统资源
插件通过接口访问
开放集成点
支持与插件的集成和通信
定义开放规范
核心系统提供的接口及版本
上下文,环境参数
回调、钩子、事件
集成规范
注册规范
名称
功能
位置
依赖
权限
定义通信机制
同步/异步
本地/远程
数据格式
实现插件
语言:受限于核心系统,确定插件的开发语言
功能:依据核心系统定义的规范实现功能
注册:按照核心系统定义的开发规范和注册规范提供注册信息
集成:确定加载方式 ,遵循通信规范
装载插件
基于注册表获取插件信息
装载机制
启动期/运行期
内存/远程
装载条件
触发条件
经典应用
操作系统
LInux
Windows
Eclipse
Rule Engine
专家系统
将人类专业知识转化为程序
用程序来解决专业问题
Rule
Condition
Action
Rule Engine
基于输入数据执行规则的专家系统
如果满足条件则执行对应的任务
ESB(Enterprise Service Bus)
通过将不同应用接入ESB以扩展系统功能
ESB是核心系统
应用是插件
应用间无直接依赖,都与ESB沟通
BPM()
通过BPM组合不同子流程形成新的流程扩展系统功能
BPM是核心系统
子流程是插件
子流程间无直接依赖
NGNIX Plus
NGNIX 通过module 为NGNIX添加新功能
NGNIX是核心,module是plugin
开源NGNIX在编译期指定要添加的模块
NGNIX Plus 可以动态添加或移除module
Servlet
Seevlet实现核心功能
插件
Filter:针对request 和response的操作
Listener: Servlet生命周期事件并执行相应命令
Spring MVC ,Struts众多功能都是基于Litenner和Filter实现
生产者消费者架构
生产者消费者模式
同步调用变成异步调用
生产数据与消费数据分离
协调不同处理速度
生产者
系统运转的动力
为下一个环节产生待处理的工作/数据
与消费者关系
重点在如何将数据发送到容器
对消费者无依赖
不关注消费者的how/when
发送顺序
消费者
从容器中获得数据,并按照自身业务逻辑处理
依赖于容器,不直接依赖于生产者
向容器确认数据已经被消费
处理后的数据
从容器中删除
保留在容器中
消费顺序
容器
消费者与生产者的交汇点
保管数据的责任
容量
保存时间
读写效率
生产者和消费者的差速器
数据分配策略
核心问题
平衡
数据不堆积
消费者无资源浪费
EDA异同
EDA
时间触发流程
重点在事件本身
不解决事件/消息如何传递的问题
Producer-Consumer
强调的是从生产端到消费端到全流程
从抽象程度来看EDA更抽象
消费策略
决定消费者如何消费数据
消费方式
PUSH
Poll
分发方式
Topic
Queue
事务性
优点
低耦合
Producer,Consumer和Container 均可独立变化
Producer和Consumer互无依赖
无事务系统对三者都无约束
异步运作
分布式部署
Producer,consumer和container均可分开部署
Producer,consumer和container自成分布式系统
各自按需扩展
平衡系统差速
通过container来平衡生产速度和消费速度
动态调节producer和consumer数量
减少资源浪费
避免生产过多数据
避免数据堆积在容器
消峰填谷
消峰
生产数据超过消费数据
缓存数据
填谷
生产数据的速度下降
消费端消费速度不变
单点流量增加不影响系统稳定性
整体系统运行于匀速状态
设计数据单元
定义
生产者放入/发送到容器的单体
容器内存储的单体
消费者消费的单体
从业务逻辑推导
数据单元具备业务含义
数据单元的颗粒度适中
完整性保证
传输过程中数据单元不可缺失
无依赖
数据单元是独立的
两个数据单元之间无影响
设计Producer
生产/发送
对发送成功的确认
始乱终弃(Fire-and-forget)
望穿秋水(Synchronous send')
云中谁寄锦书来(Asynchronous send)
序列化
数据单元变成用于网络传输的数据
JSON
AVro
Thrift
Protobuf
数据单元独立性
时间
空间
异常处理
超时
错误
重试
Consumer消费方式
推
由container发起,将数据单元推送给consumer
Consumer可以尽快获得数据
拉(pull)
由consumer发起
获取数据有滞后
设计分发模式
Queue
Point to Point
1-》1
不可重复消费
Pub/Sub
Topic
1->N
重复消费
设计消费者
反序列化
将网络数据还原为数据单元
消费确认
commit log
Ack
消费策略
批量/单体
同步/异步
幂等
设计container
集群
Replica
Nodes Master-slave
Partitions
Non-replica
只存meta data
读取转移
消息/数据存储
数据单元的存储结构
时效性
调度算法
分配数据单元到consumer
Qos
at least one
producer保证consumer至少收到一次数据单元
从业务分析container中可能有重复数据单元
Consumer实现要防重或幂等
at most once
producer 保证consumer 最多收到一次数据单元
从业务分析container中可能会对视部分数据单元
consumer可能无法读取到所需数据单元
引入第三方数据对比验证程序
exactly once
producer保证consumer收到并仅收到一次数据单元
从业务分析container中有且仅有一份数据单元
consumer无需防重
经典实现
BlockQueue
ActiveMQ
Kafka
ERP审批流程
Spring events
软件架构的评估理论
ATAM
CBAM 成本效益分析方法
生产环境全监控
cpu使用率
内存
存储空间
线程数 :线程数量 线程状态
系统测试与调优
线下压测
Jmeter
接口级别
小模块、组件
环境差异
场景多样性
线下压测
模拟模拟流量
线上导流(TcpCopy、TM双引擎测试)
单机压测
集群/全链路压测
写测试数据打标
接口读写场景混合
数据散列(冷+热)
负载测试与压力测试
压力测试
流量逐步
性能变化曲线
最佳状态
崩盘负载点
负载测试
流量逐步
性能指标
临界资源
最大负载
稳定性测试
条件
一定的负载条件下
较长时间执行
稳定性指标(控制线)
目的
不稳定因素
系统瓶颈
稳定性测试范围
链路
测试场景
构建模型
基线
控制线
KPI
分析测试结果
算出标准差、方差
计算 控制线 = 数学期望 +- 3*标准差
如何确定最佳线程数
CPU密集型 : CPU核心数+1
最小线程数:CPU核心数
IO密集型 :CPU核心数/(1-阻塞系数)(阻塞系数=阻塞时间/(阻塞时间+cpu时间))
实践出真知
增加线程数 :接口qps不变,甚至RT变长
减少线程数: 接口Qps下降
如何解决业务接口高RT的情况
异步
Future
CallBack
Guava包,ListenableFuture,SettableFuture,FutureCallBack
异步编排
CompletableFuture
系统容量规划
流量预估
系统容量预估
全链路压测
限流降级预案
网关流控
限流
QPS
全局维度
用户维度
IP维度
Sentinel
调用方限流
热点限流
准入
黑名单
白名单
DDos高防
整形
预热/冷启动
匀速通过
排队机制