微服务与 DDD
微服务架构
引入
阿里早期微服务架构重构:从巨无霸系统到微服务的改造
单体应用系统的问题:
编译、部署困难:工程庞大,构建时间长
代码分支管理困难:merge 代码耗时长
数据库连接耗尽:数据库连接使用连接池,连接池数量有限
新增业务困难
解决方案:拆分,将模块独立部署,降低系统耦合性
纵向拆分:大应用拆分为小应用
横向拆分:将复用的业务拆分出来,独立部署为微服务
历史
Web Service 与企业级分布式服务:
角色:服务提供者(Provider)、服务请求者(Requester)、服务注册中心(Broker)
关系:请求者向注册中心请求得到wsdl,然后根据SOAP协议向提供者请求数据
缺点:臃肿的注册与发现机制、低效的XML序列化手段、开销相对较高的HTTP远程通信、复杂的部署与维护手段
微服务框架
基本要求
微服务框架需要满足条件:
失效转移(Fail Over)
负载均衡:通常不会使用负载均衡服务器,而是微服务自己解决,如 netflix 的 Ribbon
高效的远程通信
对应用最少侵入(RPC)
版本管理(服务提供版本号)
Dubbo
Dubbo 如何满足微服务框架所需条件?
失效转移
负载均衡
高效的远程通信:建立长连接,而不是每次请求都重新建立TCP连接
对应用最少侵入:提供接口,直接调用
版本管理:服务保持为期半年的有效期
Service Mesh 服务网格
一个基础设施层,用于处理服务间的通信
通常表现为一组轻量级网络代理,与应用程序部署在一起,对应用程序透明
Sidecar(边车)模式:用于服务器间互相调用的先行者
微服务实践
微服务架构的落地
业务先行:先理顺业务边界和依赖,技术是手段而不是目的
先有独立的模块,后有分布式的服务
业务耦合严重、逻辑复杂多变的系统,重构需谨慎
搞清楚实施微服务的目的:业务复用/开发边界需清晰/利用分布式集群提升性能
不要用战术上的勤奋来掩盖战略上的懒惰。
命令与查询职责隔离(CQRS)
在服务接口层面将查询(读操作)与命令(写操作)隔离,实现服务层的读写分离。
事件溯源
将用户请求处理过程中的每次状态变化都记录到事件日志中,并按时间序列进行持久化存储。
精确复现任何用户状态,进行复核审计
有效监控用户状态变化,并在此基础上实现分布式事务
断路器
当某个服务出现故障,响应延迟或者失败率增加,继续调用这个服务会导致调用者请求阻塞,资源消耗增加,进而出现服务级联失效,这种情况下使用断路器阻断对故障服务的调用。
服务重试及调用超时
上游调用者超时时间要大于下游调用者超时时间之和。
最重要的是需求
Needs > Values > Principles > Practices > Tools
微服务网关
基于网关的微服务架构
网关的作用
统一接入
流量管控和容错
协议适配
安全防护(核心)
微服务网关
角色:注册中心,网关(服务消费者),服务提供者
网关管道技术
定义:网关本身没有业务,主要职责是做各种校验与拦截,可以通过管道技术连接起来
核心:责任链模式/Handlers
开放平台网关
定义:开放给第三方使用的网关,如微博、微信、淘宝、高德等。
开放授权协议 OAuth2.0:授权码授权(最常用的方式)
领域驱动设计 DDD
引入
为什么需要 DDD ?
很多项目实际情况:
用户或产品经理需求零散,变更多;
工程师在各处代码修补;
软件只有需求没有真正的设计,系统没有统一的领域模型维持内在的逻辑一致性;
功能特性不是按照领域模型,而是人的主观想象。
时间一长,问题多,需要重构。
对比
事务脚本(传统的开发模式):Controller -> Service -> Dao。特点,核心的业务都堆在 Service 中,不利于迭代。
领域模型:contract -> product -> recognitionStrategy -> revenueRecongnition。特点:设计对象,拥有自己的属性、数据、方法、计算能力。
贫血模型 VS 充血模型
战略设计
领域:一个组织所做的事情以及其包含的一切,通俗地说,就是组织的业务范围和做事方式,也是软件开发的目标范围。
领域驱动设计:从领域出发,分析领域内模型及其关系,进而设计软件系统的方法。
领域范围太大,如何下手?
通常的做法是把整个领域拆分成多个子域。如电商场景下,拆分为用户、商品、订单、库存、物流、发票等。
限界上下文:
在一个领域中,会创建一个概念上的领域边界;在这个边界中,任何领域对象都只表示特定于该边界内部的确切含义。这个边界称为限界上下文。
限定上下文和子域具有一对一的关系,用来控制子域的边界。
通常限定上下文对应一个组件,模块或者微服务。
上下文映射图:不同的限界上下文,也就是不同的子系统或者模块之间会有各种交互合作。
战术设计
实体
即领域模型对象,每个实体都是唯一的,具有一个唯一标识,如订单对象是实体,订单ID是唯一标识。
实体可能发生变化,但是唯一标识不会变化。
实体设计是DDD的核心。
值对象
仅用来做度量或描述的对象,称为值对象。
特点:不变性。值对象创建后不能再改变。
聚合
关联对象的集合,将其作为一个单元来处理数据更改。
每个集合都有一个根和一个边界。边界定义了聚合内部的内容,根是聚合中包含的单个特定实体。
聚合根:将多个实体和值对象聚合在一起的实体。
评论