- 架构设计的目的:解决 软件系统复杂度 带来的问题
- 软件复杂度的主要来源: 高性能 、 高可用 、 可扩展性 、 低成本 、 安全 、 规模
单机复杂度
- 计算机内部复杂度最关键的地方是 操作系统
- 计算机性能的发展本质是由 硬件发展驱动 的,将硬件性能充分发挥出来的关键是操作系统
- 操作系统是软件系统的运行环境, 操作系统的复杂度直接决定了软件系统的复杂度
- 操作系统和性能最相关的是 进程 和 线程
- 最早期的计算机并没有操作系统,只有 输入、计算和输出 功能,大部分时间计算机都在等待用户输入指令
- 为了解决手工输入的低效,产生了 批处理 (即把要执行的指令预先写下来,形成任务,再交给计算机执行)
- 批处理有一个明显的缺点,即计算机一次只能执行一个任务,为了进一步提升性能,发明了 进程
- 一个进程对应一个任务,每个任务都有自己独立的内存空间, 进程间互不相关,由操作系统进行调度
- 此时CPU还没有 多核 和 多线程 的概念,为了达到 多进程并行 的目的,采取了 分时 的方式
- 进程有独立的内存空间,互不相关,但进程间仍需要进行通信,方式包括: 管道 、 消息队列 、 信号量 、 共享存储
- 进程也有缺点,即单个进程内部只能 串行 处理,实际上进程内部的子任务是可以并行处理的,于是发明了 线程
- 线程是进程内部的 子任务 ,线程 共享 同一份进程数据,为了保证数据的正确性,发明了 互斥锁 机制
- 线程是操作系统 调度 的最小单位,进程是操作系统 分配资源 的最小单位
- 多进程多线程让多任务并行处理的性能大大提升,但本质上还是 分时 系统,并不能做到时间上真正的并行
集群复杂度
任务分配
- 每台机器都可以处理 完整 的业务任务,不同的任务分配到不同的机器上执行
- 1台服务器变成2台服务器,引入的 复杂度
- 需要增加一个 任务分配器
- 可能是: 硬件网络设备 (交换机)、 软件网络设备 (LVS)、 负载均衡软件 (Nginx)、 算法
- 需要综合考虑性能、成本、可维护性、可用性等
- 任务分配器与真正的业务服务器之间有连接和交互,选择合适的连接方式,并对连接进行管理
- 任务分配器需要增加 分配算法 :轮询、按权重、按负载(业务服务器需要上报状态)
- 随着业务服务器数量的增加,系统性能会提升,任务分配器本身会成为 性能瓶颈 ,任务分配器也需要 集群部署
- 任务分配器从1台变成多台,带来的复杂度: 将不同的用户分配到不同的任务分配器上
- 常见方法:DNS轮询、智能DNS、CDN、GSLB(Global Server Load Balance,全局负载均衡)设备
- 任务分配器和业务服务器的连接从 1对多 变成了 多对多 的网状结构
- 随着服务器数量的增加,状态管理、故障处理的复杂度会大大增加
任务分解
- 通过 任务分配 ,能够突破单台服务器处理性能的瓶颈,但随着业务越来越复杂,通过该方式来扩展性能,收益会越来越小
- 通过 任务分解 ,能够把原来大一统且复杂的业务系统,拆分成小而简单但需要多个系统配合的业务系统
- 能够提高性能的原因: 简单的系统更容易做到高性能 、 可以针对单个任务进行扩展
- 任务分解 不是越细越好 ,因为任务分解带来的性能收益是有 上限 的
- 拆分得越细,为了完成某个业务,系统间的调用次数会呈 指数级上升
- 系统间的调用目前都是通过 网络传输 的方式, 性能远低于系统内的函数调用
原文
http://zhongmingmao.me/2019/08/29/architecture-complexity-high-performance/