SOA(微服务), 领域设计, CAP/BASE理论, 高可用介绍
主流架构模型
- SOA
- SOA(面向服务的架构), 是一种设计方法, 其中包含多个服务, 服务之间通过相互依赖最终提供一系列的功能. 一个服务通常以独立的形式存在与操作系统进程中, 各个服务之间通过网络调用.
- 常和SOA一起提到的还有ESB(企业服务总线), 简单来说ESB就是一根管道,用来连接各个服务节点.
- 为了集成不同系统, 不同协议的服务, ESB做了消息的转化解释和路由工作, 让不同的服务互联互通.
- SOA所解决的核心问题
- 微服务架构
- 微服务是SOA的升级, 微服务架构强调的一个重点是"业务需要彻底的组件化和服务化", 原有的单个业务系统会拆分为多个可以独立开发, 设计, 运行的小应用. 这些小应用之间通过服务完成交互和集成.
- 微服务的特征
- 通过服务实现组件化 .
- 按业务能力来划分服务和开发团队
- 去中心化
- 基础设置的自动化(devops, 自动化部署)
- Docker容器技术的出现, 为微服务提供了更便利的条件, 每个服务可以独立运行在自己的进程中.
- SOA和微服务的差别
- 微服务不强调ESB企业总线, 同时进入到单个业务系统内部实现真正的组件化.
领域驱动设计及业务驱动划分
- 领域驱动设计(DDD)概念
- 开发前, 通常需要进行大量业务知识的梳理, 然后才到软件设计的层面, 最后才是开发.
- 而在业务知识梳理的过程中, 我们必然会形成某个领域知识, 根据领域知识来一步步驱动软件设计, 就是领域驱动设计的基本概念.
- 为什么需要DDD
- 业务初期, 普通的CRUD就能满足, 此时系统很清晰, 但随着产品的迭代演化, 系统变冗余, 业务逻辑变得复杂, 导致在修改一个功能时, 要追溯到这个功能需要的修改点就需要很长时间. 更别提其他不可预知的影响了.
- 领域模型追本溯源
- 早期领域模型就是数据库设计, 因为传统的项目中, 数据库是根本, 数据模型出来以后后续的开发都是围绕数据展开, 然后形成如下图的架构.
- 这种架构的问题
- service很重, 所有逻辑处理基本都放在service层.
- POJO()作为service层的非常重要的一个实体, 会因为不同场景的需求做不同的变化和组合, 就会造成POJO的几种不同模型(失血、贫血、充血), 用来形容领域模型太胖或者太瘦.
- 随着业务的复杂, 各个模块就需要修改, 这样会让原本清晰的系统不断演化变得复杂, 冗余.
- 我们设想如果不用数据库, 该怎么去设计软件, 这时候领域模型就必须基于程序本身来设计了, 这也就是DDD要考虑的问题.
- 领域设计中的几个概念
- 细化: 即划分界限上下文.
- 确认需求
- 实体: 当一个对象由其标识(而不是属性)区分时, 这种对象称为实体(Entity)
- 值对象: 当一个对象用于对事物进行描述而没有唯一标识时, 它被称作值对象.
- 聚合根
- 聚合根是领域对象中一个高度内聚的核心对象.
- 聚合根具有全局的唯一标识, 而实体只有在聚合内部有唯一的本地标识, 值对象没有唯一标识.
- 领域服务
- 一些重要的领域行为或操作.
- 它实现了全部业务逻辑并且通过各种校验手段保证业务的正确性.
- 资源库
-
- 资源封装了基础设施来提供查询和持久化聚合操作. 这样能够让我们始终关注在模型层面, 把对象的存储和访问都委托给资源库来完成.
- 他不是数据库的封装, 而是领域层与基础设施之间的桥梁.
- 领域的好处
- DDD能够让我们知道如何抽象出限界上下文上下文以及如何去分而治之(大模块分成小模块, 然后再去操作).
- DDD的限界上下文可以完美匹配微服务的要求. 在复杂系统中, 我们都需要用分治来拆解问题, 一般拆为技术维度和业务为度, 技术维度是类似MVC技术这样, 业务维度则是指按业务领域来划分系统.
- 微服务更强调从业务维度去分治来应对系统复杂度, 而DDD同样着重业务视角.
- 总结
- 领域驱动设计其实我们可以简单认为是一种指导思想, 是一种软件开发方法, 通过DDD可以将系统解构更加合理, 最终满足高内聚低耦合的本质.
分布式架构的基本理论CAP, BASE
- 首先说一下分布式的一致性问题
- 分布式系统中要解决的一个重要问题就是数据的复制. 在做数据库读写分离的场景中,假设客户端C1 将系统中的一个值K由V1更新为V2,但客户端C2无法立即读取到K的最新值, 需要在一段时间之后才能读取到. 这很正常, 因为数据库复制之间存在延时.
- 简单讲, 数据一致性就是指在对一个副本数据进行更新的时候, 必须确保也能够更新其他的副本, 否则不同副本之间的数据将不一致. 如何解决?
- 按照正常的思路, 我们可能会想, 既然是因为网络延迟导致的问题, 那么我们可以把同步动作进行阻塞, 用户2在查询的时候必须要等到数据同步完成以后再来做. 但这样使效率变低, 甚至宕机. 这时提出了一致性级别.
- 强一致性: 这种一致性级别是最符合用户直觉的, 它要求系统写入什么, 读出来的也会是什么, 用户体验好, 但实现起来往往对系统的性能影响大.
- 弱一致性: 约束了系统在写入成功后, 不承诺立即可以读到写入的值,也不久承诺多久之后数据能够达到一致,但会尽可能地保证到某个时间级别(比如秒级别)后, 数据能够达到一致状态.
- CAP理论
- 一个分布式系统不可能同时满足一致性(C), 可用性(A)和分区容错性(P), 只能满足CP/AP.
- 一致性: 所有节点上的数据时刻保持同步.
- 可用性: 每个请求都能接收一个响应, 无论响应成功或失败.
- 分区容错: 系统应该持续提供服务, 即时系统内部(某个节点分区)有消息丢失.
- BASE理论
- 基本可用: 在分布式系统出现不可预知的故障时, 允许瞬时部分可用性.
- 比如搜索的时间由1秒变成了2秒, 双11的时候部分用户被引导至降级页面.
- 软状态: 表示系统中的数据存在中间状态, 并且这个中间状态的存在不会影响系统的整体可用性. 也就是表示系统允许在不同节点的数据副本之间进行数据同步过程中存在延时.
- 比如, 待支付, 交易中, 交易成功, 交易失败, 这里的交易中就是一个中间状态.
- 数据最终一致性: 表示的是所有数据副本在一段时间的同步后最终都能达到一个一致的状态, 因此最终一致性的本质是要保证数据最终达到一致, 而不需要实时保证系统数据的强一致.
- 核心思想: 即使无法做到强一致性, 但每个应用可根据自身业务特点, 采取适当的方式使系统达到最终一致性.
分布式下的高可用设计
- 避免单点故障
- 负载均衡
- 热备(linux HA)
- 多机房(同城灾备, 异地灾备)
- 应用的高可用性
- 故障监控(系统监控/日志监控等), 自动预警
- 应用的容错设计, (服务的降级, 限流)
- 数据量(读写分离, 数据分片)
- 分布式架构下的可伸缩设计
- 垂直伸缩(提升硬件能力)
- 水平伸缩(增加服务器数量)
- CDN: 内容分发网络
- 作用: CDN的作用是把用户需要的内容分发到离用户最近的地方,这样可以是用户能够快熟获取所需要的内容.
- CDN其实就是一种网络缓存技术, 能够把一些相对稳定的资源放到距离最终用户较近的地方, 一方面可节省广域网的贷款消费, 另一方面可提升用户访问速度.
- 一般情况把静态文件(如图片, JS文件, CSS文件)放到CDN中.
- CDN算法步骤
- 当用户点击网站页面上的URL, 经过本地DNS系统解析, DNS系统最终会将域名的解析权交给CNAME指向的CDN专用DNS服务器.
- CDN的DNS服务器将CDN的全局负载均衡设备IP地址返回用户.
- 用户向CDN的全局负载均衡设备发起内容URL访问请求.
- CDN全局负载均衡设备根据用户IP地址, 以及用户请求的内容URL, 选择一台用户所属区域的区域负载均衡设备, 告诉用户向这台设备发起请求.
- 区域负载均衡设备会为用户选择一台合适的缓存服务器提供服务
- 选择的依据包括: 根据用户IP地址, 判断哪一台服务器距用户最近.
- 根据用户所请求的URL中携带的内容名称, 判断哪台服务器上有用户所需内容.
- 查询各个服务器当前的负载情况, 判断哪台服务器还有服务能力.
- 基于以上条件分析后, 区域负载均衡设备会向全局负载设备返回一台缓存服务器的IP地址.
- 全局负载均衡设备把服务器的IP地址返回给用户.
- 用户向缓存服务器发起请求, 缓存服务器响应用户请求,将用户所需内容传送到用户终端.
- 若这台缓存服务器上没有用户想要内容, 而区域均衡设备依然将它分配给了用户, 那么这台服务器就要向它的上一级缓存服务器请求内容, 直至追溯到网站的源服务器, 将内容拉到本地.
- 灰度发布
- 们的应用虽然经过了测试部门的测试, 但是仍然很难全面覆盖用户的使用场景, 为了保证万无一失, 我们在进行发布的时候一般会采用灰度发布, 也就是会对新应用进行分批发布, 逐步扩大新应用在整个及群众的比例直到最后全部完成.
- 灰度发布系统的作用在于, 可以根据自己的配置, 来将用户的流量导到新上线的系统上, 来快速验证新的功能修改, 而一旦出问题, 也可以马上的恢复.