架构师训练营第 10 周课后作业
根据微服务框架 Dubbo 的架构图,画出 Dubbo 进行一次微服务调用的时序图
关于微服务架构(中台架构、领域驱动设计、组件设计原则),你有什么样的思考和认识
巨无霸单体应用带来的问题
体验:
编译、部署困难
整个软件的体积很大,可能修改很小,但编译和部署的过程非常缓慢,一旦出错会更加耗时;
分支管理困难
代码合并过程中总会发生冲突,不同团队负责不同的业务,合并和发布的问题纠结在一起,顾此失彼;
技术:
数据库连接耗尽
因为应用包含所有的业务,每个业务可能都会连接各相关的数据库,建立连接池。随着集群规模的提升,数据库创建和维护连接的资源也逐渐成为负担;
新增业务困难
多年堆积出来的软件,依赖错综复杂,很难有人能清楚所有的细节。如果在这种状态下新增或者变更业务,可能会引起其他意外的 bug。故障率高,难以维护。
解决方案
拆分,将模块独立部署,降低系统耦合性。职责更加清晰。
纵向拆分。共用组件下沉,作为可复用的能力
横向拆分。不同领域横向拆分
最重要的服务设计,按照业务领域进行服务划分 微服务框架
为什么 WebService/SOA 没有足够成功?(不够简单) WebService 虽然有着成熟的技术规范和产品实现,以及在企业应用领域有许多成功的案例,但是也具有一些固有的缺点:
臃肿的注册与发现机制
低效的 XML 序列化手段
开销相对较高的 HTTP 远程通信
复杂的部署与维护手段
这些问题导致 WebService 难以满足互联网业务对系统高性能、高可用、易部署、易维护的要求。
微服务架构是如何解决这些问题的?
对应用最小侵入,可更换框架、可快速合并为单体状态(演变整合)
高效的远程通信,基于长连接的、二进制序列化的高效通信协议
框架层面提供服务发现和负载均衡,失效转移
版本管理,对外提供的接口向后兼容
dubbo
技术是手段,而不是目的
微服务落地实践策略和思路
微服务架构落地
业务先行,先理顺业务边界和依赖,技术是手段而不是目的
先有独立的模块,后有分布式的服务
业务耦合严重,逻辑复杂多变的系统进行服务重构要谨慎
搞清楚实施微服务的目的是什么?业务复用?开发边界清晰?分布式集群提升性能?
命令与查询职责隔离(CQRS)
在服务接口层面,将查询(读操作)与命令(写操作)隔离,实现服务层的读写分离
更清晰的领域模型
针对读写分别优化,实现更好的性能
查询服务不会修改数据,更好地保护数据
案例:拆分 UserCommend 服务/UserQuery 服务
事件溯源 将用户请求处理过程中的每次状态变化都记录在事件日志中,并按时间序列进行持久化存储
利用事件溯源,可以精确复现任何用户状态,进行复核审计
利用事件溯源,可以有效监控用户状态变化,并在此基础上实现分布式事务
断路器
当某个服务出现故障,可以使用断路器针对这种不稳定的情况进行规避。当检测到服务异常可以打开断路器,客户端的请求将不再发送至异常的实例,直到故障恢复。 主要的实现的方式如下:
通过错误计数器判定服务是否足够稳定
如果错误计数器的阈值超出稳定范围,断路器打开。与此同时,启用超时 timer
当超时 timer 过期时,进入半开状态,启动成功计数器,接入部分请求
当成功计数器进入稳定范围,则关闭断路器,否则打开断路器
三种状态:
关闭
打开
半开
重试和超时
上游调用者超时时间要大于下游调用者超时时间之和
最重要的是需求,解决业务目标,遵循商业逻辑 落地过程方法论 目标 -> 价值 -> 原则 -> 最佳实践 -> 有哪些工具
微服务网关
网关是一个服务的消费者,通过服务注册和发现调用服务提供者
网关的作用
统一接入。统一认证。高性能、高并发、高可靠、负载均衡
安全防护。防刷、黑白名单
容量管控与容错。限流、降级、熔断
协议适配。http、dubbo、jsf
网关管道技术
实现管道技术可以使用责任链设计模式
开放平台网关
开放给合作者的网关,关注的重点有:
API 接口。暴露给合作者的一组 API
协议转换。将各种 API 输入转换成内部服务可以识别的形式
安全。身份识别、权限控制。带宽、请求限流等保护措施;
审计。记录调用情况,用于监控、审计复核、计费等。
路由。将开放平台中的各种访问路由映射到内部服务。
流程。将一组离散的服务组织称一个上下文相关的新服务,隐藏细节,统一提供给开发者调用。
开放授权协议 OAuth2.0
确保第三方的服务合法的使用开放平台内的资源
领域驱动设计 DDD
贫血模型 VS 充血模型
也称:事务脚本 VS 领域模型
贫血模型
只有骨架,没有逻辑。逻辑在特定的业务逻辑层实现(在各种 Service 中)。当前的主流,思路简单,容易被接受。
充血模型
包含了对象的数据和计算逻辑。挑战更高,复杂度较高。
领域驱动设计 DDD
领域是一个组织所做的事情,以及包含的一切。通俗的说,就是组织的业务范围和做事的方式,也是软件开发的目标范围。 领域驱动设计就是从领域出发,分析领域内模型及其关系,进而设计软件系统的方法。
可以认为是简化充血模型的实现。
通过战略设计,划分模块和服务的边界及依赖关系,对微服务架构的设计至关重要。
DDD 战略设计
高层的,业务架构层面的实现。
子域
领域是一个组织所做的事情以及其包含的一切。这个范围太大,不知该如何下手。通常的做法是把整个领域拆分为多个子域,比如用户、商品、订单、库存、物流、发票等。
如何划分子域? 分析清楚某功能背后的业务真正属于哪个子域。 案例:卖家提现功能属于用户子域?订单子域?财务子域?还是直接涉及一个提现子域?
限界上下文
限界上下文是子域的物理实现,通常对应一个特定的模块、子系统或微服务。 限界上下文和子域具有一对一的关系,用来控制子域边界,保证子域内的概念统一性。
上下文映射图
不同的限界上下文,也就是不同的子系统或者模块之间会有各种的交互合作。 DDD 使用上下文映射图来设计这种关联和交互。
DDD 战术设计
编码层面的实现。
实体
领域模型对象也被称为实体,每个实体都有唯一,具有唯一的标识,一个订单对象是一个实体,一个产品对象也是一个实体。 在领域设计时要识别出实体,并根据业务确定其关键属性,这一点很重要。
值对象
并不是领域内的对象都应该设计为实体,DDD 推荐尽可能将对象设计为值对象。
值对象的一个特点是不变性,一个值对象创建以后就不能再改变了。而实体可能会经历各种状态的变迁。
聚合
聚合是一个关联对象的集合,我们将其作为一个单元来处理数据更改。每个集合都有一个根和一个边界。边界定义了聚合内部的内容。 聚合跟:将多个实体和值对象聚合在一起的实体。
案例:Product(聚合根)
1:n BackLogItem(实体)
1:n Release(实体)
1:n Sprint(实体)
一个微服务可以包含一个或多个聚合,而一个聚合不能被拆到不同的微服务中。
DDD 其它设计工具
DDD 分层架构
用户接口层 -> 应用层/服务层(很薄) -> 领域层
DDD 六边形架构
同样的领域模型,由不同的应用包装使用不同的适配器,提供给不同的调用者
界面驱动设计 vs 领域驱动设计
版权声明: 本文为 InfoQ 作者【万有引力】的原创文章。
原文链接:【http://xie.infoq.cn/article/4ff3b3f1029c8ba4d6650d0ab】。未经作者许可,禁止转载。
评论