架构师训练营 4 期 第 10 周
作业一(至少完成一项):
根据微服务框架 Dubbo 的架构图,画出 Dubbo 进行一次微服务调用的时序图
关于微服务架构(中台架构、领域驱动设计、组件设计原则),你有什么样的思考和认识?
说到中台架构,我记得第一次直播答疑的时候,就有同学问了老师一个问题,你怎么看阿里拆中台,当时老师说对于阿里来讲,建立中台和拆中台中,阿里都有能力从其中总结经验,但是如果是一个小公司,听说阿里建中台了,不加思索,也跟随其脚步,那么会把自己玩废的。
通过这段时间的学习,我觉得架构没有“放之四海而皆准”的理论,只有适合当下的业务架构才是最好的。 Eric Ries 的《精益创业》中的方法论里,提出“开发(build)- 测量(measure)- 认知(learn)”这样一个反馈循环。就是说,当你有了一个新的想法(idea)时,就把想法开发成产品(code)投入市场,然后,收集数据(data)获取反馈,看看前面的想法是不是靠谱。
那么怎么才是省事省力的原则呢,当然时在前期投入最少的时候就能验证出想法靠不靠谱,那么,初创公司业务简单没必要上微服务,买一套代码,快速开发,快速满足需求,甚至于直接使用 SAAS 快速试错都无不可。
当业务、商业模式得到一定程度上的验证,那就需要改变系统架构了,但这个时候还是不能着急,不要一上来就是领域驱动设计,那其实对于业务没什么好处,在前期我们可以使用贫血模式,等到一定阶段,发现业务边界不清晰,改动比较麻烦,那么可以考虑使用领域驱动设计改善代码结构,这个时候也没必要使用微服务架构。
当业务规模飞速发展,单体架构不能很好的满足各项需求,那么可以考虑将应用拆分,拆分的逻辑也不要太细,先进行粗粒度的拆分,逐渐适应业务需求。
所以,适合自己的才是最好的。
不过不管在那一个阶段,组件设计原则基本上都是通用的,这也是代码能够演进到下一步的基础:
组件内聚原则复用发布等同原则共同封闭原则共同复用原则
组件耦合原则无循环依赖原则稳定依赖原则稳定抽象原则
作业二:根据当周学习情况,完成一篇学习总结
本周主要讲的时模块分解
单体应用
单体应用并不可怕,可怕的时巨无霸,当单体应用出现以下的情形时,就可以认为其是巨无霸了:
编译、部署困难 整个软件的体积很大,可能修改很小,但编译和部署的过程非常缓慢,一旦出错会更加耗时;
分支管理困难 代码合并过程中总会发生冲突,不同团队负责不同的业务,合并和发布的问题纠结在一起,顾此失彼;
数据库连接容易耗尽 因为应用包含所有的业务,每个业务可能都会连接各相关的数据库,建立连接池。随着集群规模的提升,数据库创建和维护连接的资源也逐渐成为负担;
务维护或新增,都比较难 多年堆积出来的软件,依赖错综复杂,很难有人能清楚所有的细节。如果在这种状态下新增或者变更业务,可能会引起其他意外的 bug。故障率高,难以维护。
当应用到了这个阶段时,就需要考虑将单体应用进行拆分了,毕竟船小好掉头,常用的解决方案有:
纵向拆分 将一个大应用按照业务,拆分成多个小应用,独立部署
横向拆分 将复用的业务拆分出来,独立部署为微服务
微服务框架
Web Service 与企业级分布式服务
WebService 虽然有着成熟的技术规范和产品实现,以及在企业应用领域有许多成功的案例,但是也具有一些固有的缺点:
臃肿的注册与发现机制
低效的 XML 序列化手段
开销相对较高的 HTTP 远程通信
复杂的部署与维护手段
这些问题导致 WebService 难以满足互联网业务对系统高性能、高可用、易部署、易维护的要求。
微服务框架的需求
失效转移 对于大型网站的微服务而言,即使是很少访问的简单服务,也需要集群部署,同时微服务框架还需要支持服务提供者的失效转移机制,以实现服务高可用
负载均衡 对于集群部署的服务提供者,服务请求者可以使用加权轮询等手段访问,使服务提供者集群实现负载均衡
高效的远端通信 对于大型网站,核心服务每天的调用次数会达到数以亿计,如果没有高效的远程通信手段,服务调用可能会成为整个系统性能的瓶颈
对应用最少侵入 网站技术是为业务服务的,是否使用微服务需要根据业务发展规划,微服务也需要渐进式的演化,甚至会出现反复,即使用了微服务后又退回到集中式部署,微服务框架需要支持这种渐进式演化和反复。当然服务模块本身需要支持可集中式部署,也可分布式部署
版本管理 有能力为不同的消费者提供不同的版本,不强制不需要的高版本的消费者升级
微服务架构实践
微服务架构落地,需要遵循以下原则:
业务先行,先理顺业务边界和依赖,技术是手段而不是目的。
先有独立的模块,后有分布式的服务
业务耦合严重,逻辑复杂多变的系统进行微服务重构要谨慎
我们一定要搞清楚实施微服务的目的是什么,业务复用?开发边界清晰?分布式集群提升性能?只有找到目的才能有的放矢。
一些常用的微服务模式: 命令与查询职责隔离(CQRS)模式 在服务接口层面,将查询(读操作)与命令(写操作)隔离,实现服务层的读写分离:
更清晰的领域模型
针对读写分别优化,实现更好的性能
查询服务不会修改数据,更好地保护数据
事件溯源模式 将用户请求处理过程中的每次状态变化都记录在事件日志中,并按时间序列进行持久化存储
可以精确复现任何用户状态,进行复核审计
可以有效监控用户状态变化,并在此基础上实现分布式事务
断路器模式 当某个服务出现故障,响应延迟或者失败率增加,继续调用这个服务会导致调用者请求阻塞,资源消耗增加,进而出现服务级联失效,这种情况下使用断路器阻断对故障服务的调用。
主要的实现的方式如下:
通过错误计数器判定服务是否足够稳定
如果错误计数器的阈值超出稳定范围,断路器打开。与此同时,启用超时 timer
当超时 timer 过期时,进入半开状态,启动成功计数器,接入部分请求
当成功计数器进入稳定范围,则关闭断路器,否则打开断路器
三种状态:关闭、打开、半开
微服务网关
网关是一个服务的消费者,通过服务注册和发现调用服务提供者
微服务网关的作用:
统一接入。统一认证。高性能、高并发、高可靠、负载均衡
安全防护。防刷、黑白名单
容量管控与容错。限流、降级、熔断
协议适配。http、dubbo、jsf
实现管道技术可以使用责任链设计模式
开放平台网关,与业务网关不同,这是开放给第三方合作者的,有以下关注点:
API 接口 暴露给合作者的一组 API
协议转换 将各种 API 输入转换成内部服务可以识别的形式
安全 身份识别、权限控制。带宽、请求限流等保护措施;
审计 记录调用情况,用于监控、审计复核、计费等。
路由 将开放平台中的各种访问路由映射到内部服务。
流程 将一组离散的服务组织称一个上下文相关的新服务,隐藏细节,统一提供给开发者调用。
领域驱动设计
暂缓
组建设计原则
why : 软件的复杂度和它的规模成指数关系,所以如果我们将复杂的软件系统进行拆分,拆成多个更低复杂度的子系统,子系统还可以继续拆分成更小粒度的组件,也就更容易控制。也就是说,软件需要进行模块化、组件化设计
组件内聚原则 组件内聚原则主要讨论哪些类应该聚合在同一个组件中,以便组件既能提供相对完整的功能,又不至于太过庞大
复用发布等同原则
共同封闭原则
共同复用原则
组件耦合原则 组件内聚原则讨论的是组件应该包含哪些功能和类,而组件耦合原则讨论组件之间的耦合关系应该如何设计
无循环依赖原则
稳定依赖原则
稳定抽象原则
版权声明: 本文为 InfoQ 作者【引花眠】的原创文章。
原文链接:【http://xie.infoq.cn/article/9d9c3c9e60157b4f419ff974f】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论