分布式架构设计
1.分布式架构的基本理论
2.SOA架构和微服务架构
3.领域驱动设计及业务驱动划分
====================================
一. 分布式架构的基本理论
1.CAP理论
一个经典的分布式系统理论。CAP 理论告诉我们:一个分布式系统不可能同时满足一致性(C:Consistency)、可用性(A:Availability)和分区容错性(P:Partition tolerance)这三个基本需求,最多只能同时满足其中两项。
一致性(Consistency)
所有节点上的数据必须时刻保持一致
可用性(Availability)
可用性是指服务一直可用,而且是正常的响应时间
分区容错性(Partition tolerance)
系统应该持续提供服务,即时系统内部(某个节点分区)有消息丢失。比如交换机失败、网址网络被分成几个子网,形成脑裂;服务器发生网络延迟或死机,导致某些 server 与集群中的其他机器失去联系
总结:
CAP 并不是一个普适性原理和指导思想,它仅适用于原子读写的 NoSql 场景中,并不适用于数据库系统。
2.BASE理论
从前面的分析中知道:在分布式(数据库分片或分库存在的多个实例上)系统下,CAP 理论并不适合数据库事务(因为更新一些错误的数据而导致的失败,无论使用什么样的高可用方案都是徒劳,因为数据发生了无法修正的错误)。此外 XA 事务虽然保证了数据库在分布式系统下的 ACID(原子性、一致性、隔离性、持久性)特性,但也带来了一些性能方面的代价,对于并发和响应时间要求比较高的电商平台来说,是很难接受的。
eBay 尝试了另外一条完全不同的路,放宽了数据库事务的ACID 要求,提出了一套名为 BASE 的新准则。BASE 全称是 Basically available,soft-state,Eventually Consistent.系统基本可用、软状态、数据最终一致性。相对于 CAP 来说,它大大降低了我们对系统的要求。
Basically available(基本可用),在分布式系统出现不可预知的故障时,允许瞬时部分可用性
- 比如我们在淘宝上搜索商品,正常情况下是在 0.5s 内返回查询结果,但是由于后端的系统故障导致查询响应时间变成了 2s
- 再比如数据库采用分片模式,100W 个用户数据分在 5个数据库实例上,如果破坏了一个实例,那么可用性还有 80%,也就是 80%的用户都可以登录,系统仍然可用
- 电商大促时,为了应对访问量激增,部分用户可能会被引导到降级页面,服务层也可能只提供降级服务。这就是损失部分可用性的体现。
soft-state(软状态). 表示系统中的数据存在中间状态,并且这个中间状态的存在不会影响系统的整体可用性,也就是表示系统允许在不同节点的数据副本之间进行数据同步过程中存在延时;比如订单状态,有一个待支付、支付中、支付成功、支付失败, 那么支付中就是一个中间状态,这 个中间状态在支付成功以后,在支付表中的状态同步给订 单状态之前,中间会存在一个时间内的不一致。
Eventually consistent(数据的最终一致性),表示的是所有数据副本在一段时间的同步后最终都能达到一个一直的状态,因此最终一致性的本质是要保证数据最终达到一直,而不需要实时保证系统数据的强一致
BASE 理论的核心思想是:即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性
3.什么是分布式架构下的高可用设计
1. 避免单点故障
a)负载均衡技术(failover/选址/硬件负载/软件负载/去中心化的软件负载(gossip(redis-cluster)))b)热备(linuxHA)c)多机房(同城灾备、异地灾备)
b)热备(linuxHA)
c)多机房(同城灾备、异地灾备)
2. 应用的高可用性
a)故障监控(系统监控(cpu、内存)/链路监控/日志监控)自动预警
b)应用的容错设计、(服务降级、限流)自我保护能力
c)数据量(数据分片、读写分离)
3.分布式架构下的可伸缩设计
- 垂直伸缩
- 提升硬件能力
- 水平伸缩
- 增加服务器
4. 加速静态内容访问速度的CDN
CDN是ContentDeliveryNetwork的缩写,表示的是内容分发网络。CDN的作用是把用户需要的内容分发到离用户最近的地方,这样可以是用户能够快熟获取所需要的内容。CDN其实就是一种网络缓存技术,能够把一些相对稳定的资源放到距离最终用户较近的地方,一方面可以节省整个广域网的贷款消耗,另外一方面可以提升用户的访问速度,改进用户体验。我们一般会把静态的文件(图片、脚本、静态页面)放到CDN中
- 当用户点击网站页面上的内容URL,经过本地DNS系统解析,DNS系统会最终将域名的解析权交给CNAME指向的CDN专用DNS服务器
- CDN的DNS服务器将CDN的全局负载均衡设备IP地址返回用户
- 用户向CDN的全局负载均衡设备发起内容URL访问请求
- CDN全局负载均衡设备根据用户IP地址,以及用户请求的内容URL,选择一台用户所属区域的区域负载均衡设备,告诉用户向这台设备发起请求。
- 区域负载均衡设备会为用户选择一台合适的缓存服务器提供服务,选择的依据包括:根据用户IP地址,判断哪一台服务器距用户最近;根据用户所请求的URL中携带的内容名称,判断哪一台服务器上有用户所需内容;查询各个服务器当前的负载情况,判断哪一台服务器尚有服务能力。基于以上这些条件的综合分析之后,区域负载均衡设备会向全局负载均衡设备返回一台缓存服务器的IP地址
- 局负载均衡设备把服务器的IP地址返回给用户,用户向缓存服务器发起请求,缓存服务器响应用户请求,将用户所需内容传送到用户终端。如果这台缓存服务器上并没有用户想要的内容,而区域均衡设备依然将它分配给了用户,那么这台服务器就要向它的上一级缓存服务器请求内容,直至追溯到网站的源服务器将内容拉到本地。
什么情况下用CDN
最适合的是那些不会经常变化的内容,比如图片,JS文件,CSS文件,图片文件包括程序模板中的,CSS文件中用到的背景图片,还有就是作为网站内容组成部分的那些图片,都可以;
灰度发布
我们的应用虽然经过了测试部门的测试,但是仍然很难全面覆盖用户的使用场景,为了保证万无一失,我们在进行发布的时候一般会采用灰度发布,也就是会对新应用进行分批发布,逐步扩大新应用在整个及群众的比例直到最后全部完成。灰度发布是针对新引用在用户体验方面完全无感知。
灰度发布系统的作用在于,可以根据自己的配置,来将用户的流量导到新上线的系统上,来快速验证新的功能修改,而一旦出问题,也可以马上的恢复,简单的说,就是一套A/BTest系统.
二. SOA架构和微服务架构
1 SOA
SOA全称(ServiceOrientedArchitecture),中文意思为“面向服务的架构”,他是一种设计方法,其中包含多个服务,服务之间通过相互依赖最终提供一系列的功能。一个服务通常以独立的形式存在与操作系统进程中。各个服务之间通过网络调用;
跟SOA相提并论的还有一个ESB(企业服务总线),简单来说ESB就是一根管道,用来连接各个服务节点。为了集成不同系统,不同协议的服务,ESB做了消息的转化解释和路由工作,让不同的服务互联互通;
SOA所解决的核心问题
1. 系统集成
站在系统的角度,解决企业系统间的通信问题,把原先散乱、无规划的系统间的网状结构,梳理成规整、可治理的系统间星形结构,这一步往往需要引入一些产品,比如ESB、以及技术规范、服务管理规范;这一步解决的核心问题是【有序】
2. 系统的服务化
站在功能的角度,把业务逻辑抽象成可复用、可组装的服务,通过服务的编排实现业务的快速再生,目的:把原先固有的业务功能转变为通用的业务服务,实现业务逻辑的快速复用;这一步解决的核心问题是【复用】
3. 业务的服务化
站在企业的角度,把企业职能抽象成可复用、可组装的服务;把原先职能化的企业架构转变为服务化的企业架构,进一步提升企业的对外服务能力;“前面两步都是从技术层面来解决系统调用、系统功能复用的问题”。第三步,则是以业务驱动把一个业务单元封装成一项服务。这一步解决的核心问题是【高效】
2 微服务架构
微服务架构其实和SOA架构类似,微服务是在SOA上做的升华,微服务架构强调的一个重点是“业务需要彻底的组件化和服务化”,原有的单个业务系统会拆分为多个可以独立开发、设计、运行的小应用。这些小应用之间通过服务完成交互和集成。
组件表示一个可以独立更换和升级的单元,就像PC中的CPU、内存、显卡、硬盘一样,独立且可以更换升级而不影响其他单元。如果我们把PC作为组件以服务的方式构建,那么这台PC只需要维护主板和一些必要的外部设备。CPU、内存、硬盘都是以组件方式提供服务,PC需要调用CPU做计算处理,只需要知道CPU这个组件的地址即可。
微服务的特征:
- 通过服务实现组件化
- 按业务能力来划分服务和开发团队
- 去中心化
- 基础设施自动化(devops、自动化部署)
SOA和微服务架构的差别
- 微服务不再强调传统SOA架构里面比较重的ESB企业服务总线,同时SOA的思想进入到单个业务系统内部实现真正的组件化
- Docker容器技术的出现,为微服务提供了更便利的条件,比如更小的部署单元,每个服务可以通过类似Node 或者Spring Boot等技术跑在自己的进程中。
- 还有一个点大家应该可以分析出来,SOA注重的是系统集成方面,而微服务关注的是完全分离
三. 领域驱动设计及业务驱动划分
领域驱动设计的概念
领域驱动设计(DDD,Domain-Driven Design),软件开发不是一蹴而就的事情,我们不可能在不了解产品(或行业领域)的前提下进行软件开发,在开发前,通常需要进行大量的业务知识梳理,然后才到软件设计的层面,最后才是开发。而在业务知识梳理的过程中,我们必然会形成某个领域知识,根据领域知识来一步步驱动软件设计,就是领域驱动设计的基本概念
为什么需要DDD
业务初期,功能大都非常简单,普通的CRUD就能满足,此时系统是清晰的。随着产品不断迭代和演化,业务逻辑变得越来越复杂,我们的系统也越来越冗杂。各个模块之间彼此关联,甚至到后期连作者都很难说清模块的具体功能意图是啥。导致在修改一个功能时,要追溯到这个功能需要的修改点就需要很长时间,更别提修改带来的不可预知的影响面。比如说:
订单服务接口中提供了查询、创建订单相关的接口,也提供了订单评价、支付的接口。同时订单表是个大表,包含了非常多字段。在我们维护代码时,将会导致牵一发而动全身,很可能只是想改下评价相关的功能,却影响到了创建订单的核心路径。虽然我们可以通过测试来保证功能完备性,但当我们在订单领域有大量需求同时并行开发时,改动重叠、恶性循环、疲于奔命修改各种问题。
绝大部分公司都是这样一个状态,然后一般的解决方案是不断的重构系统,让系统的设计随着业务成长也进行不断的演进。通过重构出一些独立的类来存放某些通用的逻辑解决混乱问题,但是我们很难给它一个业务上的含义,只能以技术纬度进行描述,这个带来的问题就是其他人接手这块代码的时候不知道这个的含义或者可以通过修改这块通用逻辑来达到某些需求
名词概念
1 细化上下文
通过上下文划分以后,我们还需要进一步梳理上下文之间的关系,梳理的好处在于:
- 任务更好拆分(一个开发人员可以全身心投入到相关子域的上下文中)
- 方便沟通,明确自身上下文和其他上下文之间的依赖关系,可以实现更好的对接然后是基于上下文的更进一步细化建模,在DDD中存在一些名字定义
2 实体
当一个对象由其标识(而不是属性)区分时,这种对象称为实体(Entity)。
3 值对象
当一个对象用于对事物进行描述而没有唯一标识时,它被称作值对象
4 聚合根
聚合根属于实体对象,它是领域对象中一个高度内聚的核心对象。(聚合根具有全局的唯一标识,而实体只有在聚合内部有唯一的本地标识,值对象没有唯一标识,不存在这个值对象或那个值对象的说法)
5 领域服务
一些重要的领域行为或操作,可以归类为领域服务。它实现了全部业务逻辑并且通过各种校验手段保证业务的正确性。
6 资源库
资源封装了基础设施来提供查询和持久化聚合操作。这样能够让我们始终关注在模型层面,把对象的存储和访问都委托给资源库来完成。他不是数据库的封装,而是领域层与基础设施之间的桥梁。DDD关心的是领域内的模型,而不是数据库的操作。
领域驱动的好处
用DDD可以很好的解决领域模型到设计模型的同步、演进最后映射到实际的代码逻辑。
总的来说,DDD有几个好处
- DDD能够让我们知道如何抽象出限界上下文上下文以及如何去分而治之
- 分而治之:把复杂的大规模软件拆分成若干个子模块,每一个模块都能独立运行和解决相关问题。并且分割后各个部分可以组装成为一个整体。
- 抽象:使用抽象能够精简问题空间,而且问题越小越容易理解,比如说我们要对接支付,我们抽象的纬度应该是支付,而不是具体的微信支付还是支付宝支付
- DDD的限界上下文可以完美匹配微服务的要求
在系统复杂之后,我们都需要用分治来拆解问题。一般有两种方式,技术维度和业务维度。技术维度是类似MVC这样,业务维度则是指按业务领域来划分系统。
微服务架构更强调从业务维度去做分治来应对系统复杂度,而DDD也是同样的着重业务视角
注:希望大家技术越来越6p
来源:CSDN
作者:Ah_le
链接:https://blog.csdn.net/qq_30609633/article/details/103457236