4. 架构设计核心维度
4.1 边界内聚耦合
What: 确认系统边界,定义内聚耦合,如何实现高内聚低耦合
Why:分久必合,合久必分 - 解耦,架构师永远的主题
How: 理论分析,案例分享,面试实战
4.1.1 边界
- 国与国:系统边界,领域边界
- 省市县:子系统(子域)边界、模块边界、聚合边界
- 教育(高校),军事(军团):分层边界
4.1.2 聚焦内聚
功能内聚
- 模块各组成部分执行同一个功能
- 只执行这一个功能
- 专一这个功能上
顺序内聚
- 前以组成部分完成后,后一组成部分继续
- 前一模块的输出,是后一模块的输入
通信内聚
- 模块各部分使用相同输入或输出数据
过程内聚
- 模块各部分受同一控制流支配
时间内聚
- 模块各组成部分在同一时间段内执行
- 模块整体在特定时间内完成
- 例如,某一功能的初始化单元和终止单元
逻辑内聚
- 各组件的逻辑功能类似
- 由传输给模块的判断参数来确定
偶然内聚
- 模块各组成部分彼此没有关联
- 各组成部分刚好放在同一模块
4.1.3 关注耦合
7大耦合分类:
非直接耦合
- 两个模块没有直接关系
- 模块独立性最强
数据耦合
- 两个模块之间有数据值(参数)传递
- 模块间影响最小的耦合关系
标记耦合
- 两个模块与同一个数据结构有关
- 传递的是数据结构或数据结构的地址
标记耦合 vs 非直接耦合:
控制耦合
- 两个模块之间传输控制信息(开关,标签)
- 调用模块需要知道被调用模块的内部逻辑
外部耦合
- 一组模块均与外部环境相关联
- 这组模块访问同一全局变量
- 外部耦合有时候必不可少,单应尽量较少此类模块的数量
公共耦合(松散和紧密)
- 一组模块均访问统一全局数据区
松散的公共耦合 vs 紧密的公共耦合:
- 公共耦合的弊端:
- 软件可理解性降低,模块间关系复杂
- 公共软件可维护性降低,修改变量名和属性困难
- 软件可靠性降低,公共区域和全部变量无保护措施
内容耦合
- 一个模块直接操作或修改另一模块的内部数据
- 一个模块不通过正常入口访问另一模块
- 最槽糕的耦合情况,必须避免
4.1.4 高内聚低耦合
耦合关注点:
- 一个模块对另外一个模块的调用
- 一个模块向另一个模块的传递的数据量
- 一个模块施加到另一个模块的控制的多少
- 模块之间接口的复杂程度
低耦合原则
- 多用接口隐藏实现的细节
- 遵循一个定义只在一个地方出现
- 少使用全局变量
- 少用public ,多用private关键字
- 多用设计模式
- 避免直接使用SQL语句操作数据库
- 避免直接操作或调用其他模块或类(内容耦合)
- 尽量使用数据耦合,少用控制耦合
- 限制公共耦合的范围
高内聚原则
- 单一职责原则:模块的功能划分尽可能的单一
- 接口隔离原则:模块只对外暴露最小限度的接口
- 一切向功能内聚靠拢,杜绝偶然内聚
4.1.5 面试
4.2 扩展性维度
What: 架构扩展性(应用、数据)、组织扩展性、流程扩展性
Why: 大型电商平台西天取经久久八十一难
How: 理论分析,案例分享,面试实战
4.2.1 核心方法论:扩展立方体
X轴:无脑克隆
Y轴:功能分割
#### Z轴:客户分割
4.2.2 应用扩展
X轴横向克隆:弹性扩缩容、性能规划、业务解耦、环境同构
- 无状态应用,多节点克隆复制
- 负载均衡器,控制业务负载流向
- 有状态应用,状态剥离(Session处理)
Y轴服务分割:服务互不干扰,资源迭代分配、数据一致性
,业务耦合性
- 前端应用,URL拆分
- 后端应用,子系统、模块、聚合拆分
- 后台数据相应进行Y轴分割
Z轴特征分割:加速查询搜索、有状态服务、业务解耦、环境同构
- 用户UserId分割,多节点水平复制
- 地理位置分割,Set单元化
- 产品ID分割,SPU/SKU
应用扩展:套娃组合法:
4.2.3 数据扩展
X轴水平复制:CAP最终一致性,CDC便捷复制,数据高可用
存储空间浪费
- 传统SQL ,读写分离,1写多读
- NoSQL,多副本replia
- 缓存读取,横向扩展
Y轴库表分割:数据故障隔离,资源迭代分配,强一致性
业务耦合性
- 配合应用Y轴分割
- 表、库享有独立数据库集群、节点
- 微服务,康威定律
Z轴哈希取模:加速查询搜索,扩展无上限,业务解耦,强一致性
- 支持各种Key:User,SPU,SKU
- 传统SQL,分库分表(MyCat等)
- NoSQL,多shard/chunk分片
4.2.4 组织可扩展性
再论康威定律
可扩展的组织-披萨组织
- 目标一致,每条盼着吃披萨
- 人员数量较少,贝斯索推荐幸运数字:6,12
- 配合应用和数据的Y轴扩展
可扩展责任矩阵RASCI
4.2.5 流程扩展性
CMMI软件成熟度模型:
SMART原则
- S:具体:火车票查询能力扩容5倍
- M:可度量:高峰期平均5WQPS
- A: 可达成:预算翻倍,可采用云平台分流
- R:现实性:每次整改能力提升至少30%
- T:时效性:6个月之内整改完成
多快好省-扩展性实现方案
多、快
- 多:分布式架构设计、横向扩展
- 快:X轴无脑克隆和渎职
- 应用:无状态,容器化,Serverless无服务器化,云架构设计
- 数据:多副本,读写分离,冷热分离
- 中间件:缓存,最终一致性
- 工具:SQL CDC技术
好
- 好:Y轴服务和数据分割,微服务架构章节
- 服务拆分,界限上下文交互 DDD领域驱动设计
- 服务发现,服务治理,负载均衡,服务追踪 SpringCloud服务治理
省
- 省:Z轴哈希取模特征分割
- 应用:负载均衡(客户端Ribbon,服务端Nginx、K8S、Service)
- 数据,分布式多片架构,分库分表
4.2.6 案例:秒杀系统
4.2.7 面试题
4.3 高性能维度
What: 架构性能关注点,高性能流程,实现方案(缓存为王,异步为帅,分布式为将
) Why: 高并发高性能 How: 理论分析,案例分享(妥协方案),面试实战
4.3.1 高并发
TPS = 并发数/ (平均响应时间+思考时间)
并发数
体量
- 数据量:单库(数亿条记录,数百GB数据),主库(数百亿记录,数十TB数据)
- 并发:数亿在线用户,数千万活跃用户
- 交易量:平时(数十万TPS,数百万QPS),峰值
性能参数
- 交易业务:QPS,TPS,响应延时,出错率
- 流业务,吞吐量(1GB/s),处理窗口,滞后时间
- 系统,CPU、内存、存储、网络
4.3.2 高性能流程
容量规划
性能测试-负载测试
性能测试-压力测试
APM监控三境界
弹性扩缩容
4.3.3高性能实现-缓存为王
缓存为王:
- 读写:Cache Buffer
- 网络缓存 应用缓存 对象缓存
网络缓存
应用缓存
对象缓存
4.3.4 高性能实现-异步为帅
- 减少等待:磁盘、SQL、API、URL
- Y轴扩展:微服务解耦,Y轴扩展更随意
- 削峰填谷:泊松分布、银行队列
4.3.5 高性能实现-分布式为将
- X轴扩展:吞吐能力和QPS明显提升
- Y轴扩展:出错率明显降低
- Z轴扩展:延时降低,TPS/QPS明显提升
4.3.6 妥协方案-排队系统
钱:缓存为王,异步为帅,分布式为将
排队系统:
排队系统(变种):
另类的队伍-内部限流:
- 漏桶和令牌桶限流算法
- 熔断
- 降级
4.3.7 面试
## 4.4 高可用性维度
What:本地高可用,逻辑保护,容灾,多活,妥协,流程
Why:生产系统-架构设计的核心,高可用-生产系统的核心
How:理论分析,案例分享,面试实战
4.4.1 概述
可用性三叉戟
本地高可用
- 定位:本地,针对生产中心的内部故障
- 故障类型:服务器,硬盘,适配器卡,网络
- 特点:快速的恢复,自动的接管,实时简单,
业务逻辑保护
- 定位:针对致命的软件错误或人工失误的保护
- 故障类型:操作系统,数据库,应用,服务
- 特点:数据保护为主,人工决策,人工干预,人工追数
容灾多活
- 定位:异地,针对生产中心的机房或大面积设备故障
- 故障类型:HA方案失效,主站点(基础架构)失效,自然灾害
- 特点:恢复时间较长,手动切换负载,涉及内外多个部门、容忍部分数据丢失,有必要制定灾难恢复计划
4.4.2 本地高可用-集群、分布式
- CAP理论:
集群架构CA
分布式架构AP
- 分布式系统设计
- 一致性、脑裂、雪崩、击穿
- 分布式应用、分布式中间件、分布式数据库
4.4.3 数据逻辑保护
影响高可用的真正因素
逻辑保护三部曲
逻辑保护技术
- 备份
- 快照
- CDP连续数据保护
4.4.4 面试
4.5 安全性维度
What: 流程安全性,架构安全性,安全实现方案概述
Why:企业成长过程不可避免的痛,讳疾忌医的那些日子
4.5.1 安全大事件
人在河边走,哪能不湿鞋
4.5.2 流程安全性
安全基本原则 CIA
安全框架
安全评估方法
- 安全测试:SAST静态测试,IAST交互式测试,安全扫描
- 威胁模型:攻击树分析,DREAD风险评估
- 渗透测试:红蓝对抗,白帽黑帽
4.5.3 架构安全性
安全五芒星
#### 物理安全
数据安全
- 访问权限:责任分层,最小特权
- 数据加密:对称密匙,非对称密匙,数字签名
- 数据保护:数据逻辑保护,数据高可用
通信安全
- 最强之剑:网络攻击
- DDoS拒绝服务
- DNS劫持
- 重放攻击
- ARP地址解析欺骗
- 最强之盾:网络防御
- WAF应用防火墙
- IDS/IPS入侵检测和防
- VPN/IPSEC安全通道加密
- PGP邮件加密
- TLS HTTP隧道加密
身份安全
- Authentication认证:目录管理,用户认证
- Authorization授权:MAC\RBAC\OAuth第三方授权
- Audit审计:审计管理控制,审计技术控制
软件安全
- 操作系统安全:病毒、木马
- 数据库安全:防止SQL注入,防止推理攻击
- Web应用安全:防止XSS跨站点脚本攻击,防止重放攻击
4.5.4 面试
4.6 伸缩性维度
What:伸缩性场景、思路、实现方案(入口层、应用层、基础架构层、有状态、无状态)
Why:人生有潮起潮落,企业也不例外
4.6.1 主要场景:电商的秒杀和抢购
- 热点业务:支付、下单、添加购物车、商品详情页、搜索
- 热点数据:秒杀产品、动态数据、静态数据
- 思路:时间与空间转化、
系统伸缩性
微服务伸缩
基础设施、系统资源、网络引流
4.6.2 无状态应用弹性伸缩
无服务器话 Sweverless
- 应用无状态
- 常见编程方式:函数式编程、响应式编程
- 常见业务模式:事件驱动、流驱动
- 从0资源-> 无穷大
Kubernetes 弹性伸缩实战
4.6.3 有状态应用弹性伸缩
有状态应用如何弹性伸缩?
- 将有状态应用进行区分:共享磁盘模式和Share Nothing模式
- 共享磁盘模式 -> 无状态应用
- Share Nothing 模式 -> 采用合适的集群管理方式和CAP目标
向无状态应用转移
- 结构化数据 -> 共享数据库
- 非结构化数据 -> 共享缓存,对象存储,搜索引擎等
- 减少文件系统依赖,如cdn直接对接对象存储等
Share Nothing 架构
- CAP:优化可用性和分区性,弱化一致性
- 集群管理:优化选举,仲裁、阶段提交、副本、分片管理
- 资源预配置
4.6.4 面试
6. 架构设计模式
何谓分层?
- 将系统按照职责拆分和组织
- 上层依赖直接下层
- 下层不可以依赖上层
- 不可以跃层访问
6.1 分层架构模式
- 网络分层OSI 7层架构
-
CS、BS架构
-
企业应用三层架构
6.1.1 为何分层
复杂度隔离
- 隔离业务复杂度和技术复杂度
- 解决不同层的问题可以采用不同的技术栈
- 每层变化速度不一致
防止错误传播
- 防止错误传播
- 降低错误影响
- 防水仓设计
层自治
- 本层功能内聚
- 自主决策
- 只有本层的只是
- 知道的越少,泄密的可能性越小
- 受影响的可能性小
6.1.2 优点
高内聚
- 每一层的任何变更最多影响自身和上一层
- 专注自身功能,其它层的影响被屏蔽
- 单一职责
低耦合
- 每一层只依赖下一层
- 单向依赖
- 通过接口交流
易扩展
- 功能扩展,影响仅限本层
- 内聚性,易于横向扩展
- 独立部署,易于纵向扩展
- 每层定义了清晰的边界,扩展发生在不同边界,符合开闭原则
可维护
- 分供合作,开发者关注点集中
- 每一层可以依据接口并行开发
- 每一层功能单一,代码易于理解
可测试性高
- 每层对外提供固定接口,可以直接测试接口
- 分层测试
6.1.3 缺点
性能下降
- 分层必定引入新的通信开销
- 层信息不能泄露,导致每层都有数据转化发生
- 不能跨层访问,无法通过减少调用链路
开发成本上升
- FULL stack 少且难以培养
- 跨组织沟通成本
- 任何变更可能都需要多层参与
6.1.4 如何设计分层
依赖规则
- 越向内越具体,越朝内越抽象 - 外圈是软件,内圈是规则 - `依赖关系只能从外向内`
定义职责
- 高层表示规则,底层实现细节
- 逻辑内聚自治分组
- 依据组织职责分工
选定技术栈
- 根据每层的需求各自选定
- 借鉴成功案例
- 部署方式
代码抽象和分层
- 层对外暴露的接口,隐藏实现细节
- 实现依赖抽象,抽象不可依赖于实现细节
- 代码不跨层使用,只依赖于直接的下一层
集成
- 集成前做单元测试
- 根据接口和技术栈确定集成方式
- 集成联调
6.1.5 分层案例
MVC
- Model:Domain model 和业务逻辑
- View : 展示数据和用户交互
- Controller:
- 接收输入并转化为对model的操作
- 将model转化成view能展示的数据
6.1.6 面试
- HTTP 和 TCP/IP 连接的关系
- 什么是MVC架构,采用何种技术实现MVC?
6.2 事件驱动架构模式EDA
6.2.1 何为EDA?
Notification
-
源系统发送消息通知其他系统状态改变
-
接收方响应非必须
-
发送Event逻辑与处理Event逻辑无依赖,独立变化
-
解耦,各自扩展
-
事件驱动架构模式是一种异步分发事件的架构模式
-
用于高扩展且低耦合的系统
-
事件为核心,一系列解耦、单一功能的事件处理器
经典应用NIO
- 针对不同的IO EVENT 分配不同的handler
- Selector: 监控哪些Channel有IO event
- SelectionKey: 维护IO event 的状态和绑定的handler
经典应用Nginx
- nginx的工作进程一直监听端口并等待Event
- Event 是有新建的连接所触发
- 所有的连接都会被分配到一个对应的状态机
6.2.2 优点
整体灵活性
- 架构能否在不断变化的使用场景下快速响应
- 事件处理器组件目的单一、高度解耦,可以独立变化
- 代理拓扑结构比中介拓扑结构调度会更容易
- 事件中介与事件处理器是耦合的
- 代理模式完全解耦
可扩展性
-
高度解耦,独立变化
-
横向扩展
- 不同组件的运行运行节点数均可自行调整
- 组件本身可以自行决定是否在拆分实现
-
纵向扩展
- 计算密集型还是内存密集型,按需调整
-
性能
- 细粒度的事件处理器有利于提高性能
- 整体架构是异步并行有利于提高性能
-
异步部署
- 高度解耦的事件处理器组件让整体部署相对容易
6.2.3 缺点
可测试性
- 单元测试无差异
- 集成测试难
- 组件众多
- 异步
可维护性
- 分布式部署
- 异步
- 异常处理难
- 代码可读性
性能
- 分布式消息(事件)传递会减低性能
6.2.4 案例
短信验证码
6.3 微内核架构
6.3.1 定义
- 微内核
- 核心功能
- 资源封装
- 插件
- 可插拔
- 资源封装
- 硬件接口
- 系统资源访问接口
- 环境上下文访问接口(context)
- 系统事件接口
- 定义插件规范
- 使用场景
- 规则
- 条件
- 核心功能
- 支持系统运作的最小功能集
- 职责分离
- 通用流程由核心系统定义
- 核心定义规范,插件具体实现
6.3.2 插件
- 核心系统能力扩展
- 遵循核心系统规范
- 实现其逻辑外延和业务逻辑
- 单一职责
- 专注其独立功能
- 只能通过核心提供的接口操作系统资源
- 插件间无依赖
- 尽可能避免依赖其他插件
- 只依赖于核心
- 隔离
- 插件不影响核心
6.3.3 优点
-
符合开闭原则
- 核心系统封闭
- 插件提供开放性
- 整体系统可持续升级
-
良好的隔离性
- 核心系统可以关闭插件
- 错误的传播有限
- 各自独立升级改进
-
灵活性
- 核心系统保持稳定,将变化尽量隔离在插件层
- 插件根据核心提供的接口和规范来提供丰富的功能
- 整体保持开放,持续进化
-
可测试性
- 核心系统和插件系统可以分开测试
- 插件可以运行在模拟环境
-
性能
- 通过简化核心系统,提高其性能
- 插件按需加载,降低资源损耗
- 可以动态关闭插件以保护核心系统
-
易于部署
- 插件可在运行时动态添加到核心系统
- 减少核心系统停机时间
6.3.4 缺点
- 开发难度高
- 需要分离核心功能与插件功能
- 插件需要可以热插拔
- 需要注册专门的协议和通信协议
- 可扩展性不高
- 主要用于开发产品,不考虑扩展性
- 不以可扩展性见长
- 可以结合其他模式获得扩展性
6.3.5 使用微内核
设计系统核心
- 定义核心功能:实现MVP
- 封装系统资源:插件通过接口访问
- 开放集成点:支持与插件的集成和通信
定义开放规范
- 核心系统提供的接口及版本
- 上下文context,环境参数
- 回调callback 钩子hook 时间event
- 继承规范
注册规范
- 定义通信机制
- 同步、异步
- 本地、远程
- 数据格式
- 实现插件
7. 架构设计评估
7.1 如何评估服务性能
7.1.1 评估理论ATAM
Architecture Tradeoff Analysis Method
1. 表述部分-开局
- PMO
- 产品:项目目标,上下文/功能点
- 架构:架构 vs 业务,组件/流程图,上下游链路数据
2. 调查分析-对线
- 产品/架构:高优先级场景,实现难度(L,M,S),安全性、性能预估等
3. 场景讨论-打团
- 相关人士:
- 高优先级场景:架构技术方案
- 风险点和待确认事项
- 识别架构师没有识别的风险
报告生成-会议纪要
- PMO
- 共识事项
- 跟进事项
- 风险点
7.1.2 CBAM成本效益分析方法
7.1.3 服务监控指标和调优思路
- 生产环境全监控
- CPU使用率
- 内存, 内存泄露
- 存储空间
- 线程数,线程监控,线程数量,线程状态
7.1.4 面试
7.2 系统测试与调优指标
7.2.1 线上压测,线下压测
线下压测
- 接口级别
- 小模块,组件
- 差异(环境差异,场景多样性,单机性能)
线上压测
- 模拟流量,热点
- 线上导流:TM双引擎测试,TCPCopy(流量回放)
- 单机压测
- 集群、全链路压测
- 考虑(写测试数据打标,接口读写场景混合,数据散列(冷+热))
7.2.2 负载测试和压力测试
压力测试
负载测试
7.2.3 稳定性测试控制图
7.2.4 最佳线程数
理论:
实践:
- 增加线程数:
- 接口QPS不变,甚至RT变长 (警告)
- 减少线程数:
- 接口QPS下降
7.2.5 解决接口高RT的情况
- 异步 CompleteFuture
- 异步编排:
7.2.6 并发用户模式& RPS模式
- VU:虚拟用户并发数
- RPS:Request per second (TPS)
7.2.7 全链路压测
7.3 系统容量预估
7.3.1 业务容量规划
- 流量预估
- 历史数据回测(线上数据,模型预测),峰值脉冲误差较大(限流)
- 系统容量评估
- 漏斗模型流量分配,业务容量/单机吞吐(2C8G)
- 流量预估结果
- 全链路压测
- 集团军大练兵,数据工厂-辅助,等量线上基础数据
- 尽可能模拟双11,压测标识-DPS,影子标记
- 限流降级预案
- 误差兜底
- 请求-> RT(阈值判定,降级和弹性) -> 用户重试-> GG
7.3.2 集群部署和水位调配
7.3.3 容量精调之单机压测场景
-
流量复制
- 真实流量复制,场景真实
- 流量重播,是否具备线上数据隔离方案
-
流量转发
- 网关权重
7.3.4 混合部署技术
- 资源分时复用,
- 响应时效-实时、离线
7.3.5 限流维度& 前端柔性
-
网关流控
-
后端降级/客户端限流等
-
前端柔性
错峰/削峰
7.3.6 线上应急预案
7.3.7 三高系统稳定性
7.3.8 线上异常回退
7.3.9 面试
7.4 系统设计的前瞻能力
7.4.1 案例分享:商品中心
- 方案设计,有始有终