微服务 &DDD& 中台
随着业务不断发展,带来系统的复杂度的增大,目前行之有效的方法是通过 DDD 领域模型的设计为指导实现微服务的边界划分和依赖关系组织,并将可复用的基础业务能力的沉淀形成平台化,在不断演化形成中台化。
微服务
1. 面临什么样问题,需要微服务
巨无霸应用系统带来的问题:
i) 编译、部署困难
ii) 代码分支管理困难
iii) 数据库连接耗尽
iv) 新增业务困难
解决方案:拆分,将模块独立部署,降低系统耦合性。包含:纵向拆分,将一个大应用拆分为多个小应用;横向拆分,将复用的业务拆分出来,独立部署。
2. Web Service 与企业级分布式服务
存在一些固有的缺点:
i) 臃肿的注册与发现机制
ii) 低效的 xml 序列化手段
iii) 开销大的 HTTP 远程通信
iv) 复杂的部署与维护手段
3. 微服务架构需要具备的能力
大型互联网系统,除了 web service 所规范的注册与发现,服务调用等标准功能,还包含:
i) 失效转移(Fail Over): 集群部署,支持服务提供者的失效转移机制,以实现服务高可用
ii) 负载均衡:服务提供者使用集群部署,可使用路由算法实现负载均衡
iii) 高效的远程通信:调用次数达到数亿次,通信不能成为瓶颈
iv) 对应用最少侵入:支持应用集中式部署,也可分布式部署
v) 版本管理:服务提供者提供历史版本的支持
4. 微服务框架 Dubbo 架构
5. RPC 框架实现原理
通讯协议: 包含 网络通信协议(TCP, UDP), 编码传输协议(二进制,文本,协议头格式)
私有通讯协议优点:减少冗余数据传输、灵活满足自定义通讯需求,最大程度满足性能需求。
Dubbo 避免队头阻塞:使用 requestId, 请求 ID。
序列化协议包含:kryo, Hession, Protobuf, JSON
6. Service Mesh 服务网格
Service Mesh 是一个基础设施层,处理服务间的通信,与应用程序部署在一起,而对应用程序是透明的。使用 Sidercar 模式设计的。
通过 Service Mesh 实现了的服务的网格化
7. 基于网关的微服务架构
网关作用或功能:统一接入(高性能、高并发、高可用、负载均衡),流量管控与容错(限流,降级,熔断),协议适配(http, dubbo),安全防护(防刷,黑白名单)
网关主要职责是各种校验和拦截,可通过管道技术连接起来。实现管道技术可使用责任链设计模式。
异步网关与异步微服务框架实现
网关 toB 能力支持(开放平台),除了基础的网关能力,还包含:商户鉴权,服务鉴权,用户授权服务,加解密,加验签,服务审计,服务计费等。
开放授权协议 2.0, OAuth2.0 有四种授权方式:授权码、隐式授权、资源所有者密码凭据、客户端凭据。
8. 微服务的实践
微服务架构落地方法论:
i) 业务先行,理顺业务边界和依赖,技术只是手段
ii) 先独立各个模块,再实现分布式服务
iii) 业务耦合严重,逻辑复杂多变系统进行微服务重构需谨慎
iv) 微服务目的是? 解决什么问题? 业务复用,开发边界确定,分布式集群提升性能
微服务实现注意技术点:
i) 命令与查询职责隔离(CQRS): 在服务接口才能将查询(读)与命令(写)隔离,实现服务层的读写分离。可实现更好的性能,更好的保护数据。
ii) 事件溯源:将用户请求处理过程中每次状态变化都记录到事件日志中,并按时间序列进行持久化存储。可实现精确复现任何用户状态,进行复核审计,可有效监控用户状态变化,并在此基础上实现分布式事务。
iii) 断路器:当某个服务出现故障,响应超时和失败率增高,继续调用会造成雪崩。需使用断路器阻断对故障服务的调用。断路器有三种状态:关闭、打开,半开。
iv) 服务重试、调用超时:上游调用者超时时间要大于下游调用者超时时间之和
微服务落地其实最重要的需求,有一个倒三角的模型:
DDD
1. 为什么需要 DDD
项目时间一长,出现各种问题,导致需求延期,线上 bug 不断,有的想推倒重来,有的又想草草了事。具体表现:
i) 产品需求零零散散,忽左忽右, 到产品发展路线不明确
ii) 工程师为了实现功能和修改 bug, 不择手段
iii) 整个开发流程,只有需求,没有设计
iv) 系统没有统一的领域模型维持内在逻辑的一致性, 功能特性按照主观想象设计
需要领域模型设计,来规范产品的需求和业务的开发
2. 目前开发模型与领域模型区别
当前开发模式
按事务脚本方式实现功能,调用流程:Controller -> Service -> Dao
其实就是贫血模型:有的对象只有方法没有成员变量,有的只有成员变量没有方法
领域驱动模式
按领域模型方式实现功能,调用流程:实体-> 实体-> Strategy -> 实体
其实就是充血模型:对象包含数据和计算逻辑
3. DDD 基本概念
领域:一个组织所做的事情以及包含的一切
子域:把整个领域拆分成多个子域,如何划分?需要根据业务和运营的理解
限定上下文:子域中,创建一个领域边界。与子域 1 对 1 关系,用来控制子域的边界。通常限界上下文对应一个组件或一个模块,或一个微服务
上下文映射图:不同子系统或模块之间会有各种的交互合作,用上下文映射图设计这种交互。
实体:领域模型中的对象,每个视图是唯一的,具有唯一标识,实体可能会发生变化,但标识不会变化。DDD 设计的核心, 把握实体的特征,承担的职责,分析是要放在业务场景和界限上下文中。
值对象:仅仅用来做度量或描述的对象应该设计为值对象,特点是不变性,一个值对象创建后不能再改变了。
聚合:一个关联对象的集合,每个集合都有一个根,一个边界。聚合根:将多个实体和值对象聚合在一起的实体。
DDD 分层架构:用户接口层 --> 应用层(组合调用/事务控制) --> 领域层
DDD 六边形架构:领域模型封装成一个相对独立的模块,而不同外部系统通过不同的适配器与领域模型交互,访问接口调用不同的适配器实现功能。
4. DDD 战略设计 & 战术设计
战略设计:领域、子域、界限上下文、上下文映射图,通过战略设计,划分模块和服务的边界及依赖关系,对微服务架构设计很重要。
战术设计:实体、值对象、聚合、CQRS、事件溯源
5. DDD 实践
不能单纯为了 DDD 而 DDD, 而一定是为了解决某些问题,下面是分步实现设计和落地的实践:
i) 当前系统设计,问题汇总和讨论:代码混乱,迭代困难,部署麻烦,bug 升高
ii) 分析问题:子系统划分不合理,有的子系统承担 80%-90%功能,其他系统只占 10%-20%
iii) 重新梳理业务规则和边界,明确业务术语。DDD 战略设计,领域建模
iv) 技术构架选项与落地方案验证。DDD 战术设计,样例代码
v) 任务分解与持续重构。重构和业务迭代有机结合
组件设计原则
随着软件代码规模的不断扩大,复杂度成指数级的增长。为了软件的稳定性、开发效率,需将系统划分为一个个组件进行维护,组件依赖关系按层次结构进行组织。组件的划分需满足“高内聚,低耦合”原则。
1. 组件内聚原则
讨论是哪些类应该聚合在同一个组件中,组件提供功能,既要相对完整,又不能过大。具体包含:
复用发布等同原则
软件复用的最小粒度应该等同于其发布的最小粒度。
组件是软件复用和发布的最小粒度软件单元,这个粒度是复用的粒度,也是发布的粒度。
版本号约定建议:
i) 格式:主版本号.次版本号.修订号
ii) 主版本号升级,表示组件发生了不向前兼容的重大修订
iii) 次版本号升级,表示组件进行了重要的功能修订或 bug 修复,但向前兼容的
iv) 修订号升级,表示组件进行了不重要功能修订或 bug 修复
共同封闭原则
将那些会同时修改,并为了相同目的而修改的类放到同一组件中。反之放在不同的组件中。
共同复用原则
不要强迫一个组件的用户依赖他不需要的东西, 而应该将互相依赖共同复用的类放在一个组件中。
2. 组件耦合原则
讨论组件之间的耦合关系应该如何设计
无循环依赖原则
组件依赖关系中不应该出现环,形成循环依赖。
稳定依赖原则
组件依赖关系必须指向更稳定的方向,不稳定的组件应该依赖稳定的组件,而不能反过来。 组件不应该依赖一个比自己还不稳定的组件。
稳定抽象原则
一个组件的抽象化程度应该与其稳定性程度是一致。一个稳定组件应该是抽象的,而不稳定组件应该是具体的。可设计一组接口对外提供服务。
组件的边界与依赖关系划分,不仅需要考虑技术问题,其实更多需考虑适合公司的业务和运营的现状和发展,还需考虑公司组织架构、部门利益。
中台
中台是一个服务的演进和进化, 演进过程:微服务 --> 可重用组件 --> 平台化(业务抽象,领域细分) --> 中台化(定义上下文和规则),是平台化的下一站,是对平台不断进行自身的治理演进,打破技术边界,拥抱和容纳业务,具备更强的业务属性的过程。中台关注为前台业务赋能,真正为前台而生。
中台是企业级能力复用平台,需站在企业级的战略进行分析、定义、设计,并持续迭代,再落地实施,完成交付。是企业基于已有的基础能力,能快速构建新的业务形态,找到新的发展机会。
版权声明: 本文为 InfoQ 作者【dony.zhang】的原创文章。
原文链接:【http://xie.infoq.cn/article/bdd2c684d308aa85b5be7fddd】。文章转载请联系作者。
评论