目录
单体应用架构
就是把所有的功能都写在一起,打包成一个应用,直接部署。
当我们的业务不断扩大,就会出现可靠度低、不易于扩展等问题;
业务驱动技术发展
集群架构
使用前后端分离,一个Nginx可以负载均衡发给后面多个Tomcat,并让图片、文件和数据存储分离。
不能实现指定业务扩展机器;冗余仍然存在,会产生级联问题
垂直化架构
将服务拆分成多个子系统,各系统间隔离,系统调用自己库中相关的表
代码冗余,如果一个业务接口共用只能在每个系统中都写一遍
SOA架构
实现面向服务,对公共模块进行抽取,解决信息孤岛问题。是中心化的,由一个ESB总线去管理这些服务;
耦合度仍然很高;比如电商系统要进行秒杀操作,要调用一系列服务,其中一个服务不可用就会导致这个操作无法进行
微服务架构
服务的细粒度化,没有总线,注重的是应用级别的服务划分,耦合度降低,模块之间边界清晰,服务之间通过轻量级的通信机制相互协调
优点
- 耦合度降低,模块之间边界清晰:团队独立、技术独立
- 技术选型丰富,不同服务用不同语言
- 扩展方便,比如商品访问量大,就只用给商品服务扩容
- 隔离性强:避免级联问题
缺点:增加网络开销,性能变差;还有网络可靠性问题
各服务之间如何通信
同步
REST:一种架构风格,表述性状态转移,通过HTTP的方式对服务端资源获取或操作,请求中必须包含资源路径、数据等所有必要信息,客户端和服务端是无状态的
Spring提供的RestTemplate
就是通过HTTP协议完成通信;而Feign对此进行了封装,可以让我们更优雅的实现HTTP请求发送。
RPC:远程过程调用,就是像调用本地方法一样调用远程方法。可以基于TCP/UDP,也可以基于HTTP协议进行传输;
客户端和服务端维护了一个函数对应表,将参数序列化字节流,通过TCP协议传输(部分使用HTTP),获取到的结果再反序列化成数据
例如gRPC、Dubbo
Rest基于HTTP,效率低,灵活度高
RPC大部分基于TCP,效率高,灵活度低
异步
消息队列
分布式
由多个节点组成的系统,多个节点协同操作;
分布式搜索引擎;分布式缓存;
- 微服务是架构设计方式,分布式是系统部署方式
- 把一个应用集群部署是分布式但不是微服务
优点
- 高性能,机器的增多
- 高可用,故障对整个系统的影响小
- 高扩展,节点扩容方便
需要解决的问题
- 多节点之间通信
- 并发安全性问题
- 服务雪崩
- 调优:jvm ;IO;数据库
- 高可用:负载,故障处理策略
- 伸缩性:垂直,水平伸缩:访问量、数据量、计算能力;
系统设计目标
高并发
高并发意味着大流量,我们需要运用技术手段抵抗流量的冲击,能让流量更平稳地被系统所处理
淘宝双十一;微博热点;秒杀系统;订单系统;
高性能
系统的并行处理能力;直接挂钩用户的体验;要让系统的响应时间尽可能短,吞吐量尽可能大
QPS:每秒查询率(吞吐量的一种指标)
实现方案
增加机器
- 集群部署,增加服务器节点,通过负载均衡减轻单机压力。负载均衡可以使用Nginx或者LVS,Nginx还能存放静态资源。
通信
- 减少IO次数,比如数据库的批量读写
- 减少IO时的数据包大小,包括采用轻量级的通信协议、合适的数据结构、去掉接口中的多余字段、减少缓存key的大小、压缩缓存value等。
- 各种池化技术的使用和池大小的设置,包括HTTP请求池、线程池(考虑CPU密集型还是IO密集型设置核心参数)、数据库和Redis连接池等。
处理请求
- 异步化,将次要流程通过多线程、MQ、甚至延时任务进行异步处理。
数据存储
- 分库分表和索引优化,以及借助搜索引擎解决复杂查询问题
- 多级缓存技术,包括静态数据使用CDN、本地缓存、分布式缓存等,产生缓存穿透、缓存击穿、缓存雪崩、缓存一致性等问题
自身优化
- 程序逻辑优化,算法优化
- JVM优化,包括新生代和老年代的大小、GC算法的选择等,尽可能减少GC频率和耗时。
- 锁选择,读多写少的场景用乐观锁,分段锁
- 数据库优化:引擎选择、表结构、索引、SQL优化
整体设计优化
- 微服务划分:按照角色 or 按照数据源
高可用
表示系统可以正常服务的时间,减少故障次数
可用性 = 平均故障时间 / 系统总运行时间
基本要达到四个九99.99%
实现方案
- 网关限流,计数限流、漏桶算法、令牌桶算法
- MQ削峰填谷:达到对流量的整形,提高下游服务可靠性
- 节点故障转移,主从切换(redis的哨兵模式或者集群模式、MySQL的主从切换等)
- 防止微服务雪崩:保证核心服务,牺牲非核心服务,必要时进行熔断;防止雪崩
- 拦截器:对不正当请求的拦截
高扩展
表示系统的扩展能力,流量高峰时能否在短时间内完成扩容,更平稳地承接峰值流量,需要架构不改变,通过增加机器来提高性能
扩展性 = 性能提升比例 / 机器增加比例
像MySQL这种有状态的存储服务通常是扩展的技术难点,如果架构上没提前做好规划(垂直和水平拆分),就会涉及到大量数据的迁移,所以我们就要在设计系统时提前考虑
实现方案
要提高系统的扩展能力,先要进行拆分,数据库分库分表、业务层MVC分层、服务拆分,这样才能指定模块的扩展,还要考虑数据分布问题,如Redis分片集群中数据如何分布,才能让在扩展的时候减少数据迁移。
相关术语
中台业务
前台是最终向用户服务的业务能力(淘宝、天猫…);中台提供了前台业务间共享的业务逻辑、计算能力和数据,提炼了各业务线的共性需求,旨在降低成本、加强管控。
业务线不稳定或者不断扩充,就会出现很多业务线不断造轮子的情况,而有了中台的抽取,就会减少内耗,降低成本
中台抱大业务大腿,小业务抱中台大腿,中台优先满足大业务,大业务需要该中台,小业务被迫升级,所以中台是某些业务的中台,不是所有业务的中台;对于创新性业务的产生,中台就需要不断的收编来扩充自己的能力,造成屎山情况
中台写的代码不多,但需要不断和新业务功能讨论、设计,划分哪些是共性需求,哪些是特性需求
微服务&中台
微服务是架构理念,中台是将对业务的服务聚合在一起
平台&中台
平台是对技术抽取,称为技术平台,与业务无关,例如nacos,redis集群。中台是对共性业务的抽取,与业务相关
领域驱动设计
领域驱动设计DDD是一种设计思想,它可以同时指导中台业务建模和微服务设计(中台本质是业务模型,微服务是业务模型的系统落地),领域驱动设计强调领域模型和微服务设计的一体性,先有领域模型然后才有微服务,而不是脱离领域模型来谈微服务设计。
微服务拆分困境产生的根本原因:不知道业务或者微服务的边界到底在什么地方。
DDD 核心思想:通过领域驱动设计方法定义领域模型,从而确定业务和应用边界,保证业务模型与代码模型的一致性
详情见: 领域驱动实践总结
有界上下文
有界上下文是域驱动设计的核心模式。DDD 战略设计部门的重点是处理大型模型和团队。DDD 通过将大型模型划分为不同的有界上下文并明确其相互关系来处理大型模型
康威定理
设计系统的架构受制于产生这些设计的组织的沟通结构。通俗的来讲:产品必然是其(人员)组织沟通结构的缩影,组织决定产品形态
微服务架构中的DRY
不要重复自己。它基本上促进了重用代码的概念。这导致开发和共享库,这反过来导致紧密耦合
消费者驱动合同CDC
这基本上是用于开发微服务的模式,以便它们可以被外部系统使用。当我们处理 微服务时,有一个特定的提供者构建它,并且有一个或多个使用微服务的消费者。
持续集成CI
持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误
金丝雀释放
一种降低在生产中引入新软件版本的风险的技术。这是通过将变更缓慢地推广到一小部分用户,然后将其发布到整个基础架构,即将其提供给每个人来完成的
分布式id生成方案
- UUID:通用唯一标识码,不需要中央控制器;速度快;占用空间多,不是递增的数据;
- 数据库主键自增:占用空间小;并发性能不高,受限于数据库性能;分库分表改造复杂,自增容易泄漏数据
- Redis自增ID:使用Redis的incr命令;使用内存,并发性能好;基于内存容易丢失数据,自增容易泄漏数据
- 雪花算法:不依赖于外部组件,性能好;时钟回拨
雪花算法生成的ID由哪些部分组成?