文章目录
前言
微服务是如今比较热门的话题,但是到底什么是微服务,微服务带来了哪些好处,又引入了什么问题,该如何设计微服务等等。
很多第一次了解微服务的同学可能会觉得这些内容很多,会对微服务产生距离感与畏惧感,当然我在最开始也是这样。
所以一开始我直接找了一些网上所谓微服务实战的教学视频,不管是什么语言实现的基本上都是那一套内容:从服务注册与发现,到服务治理中的熔断与限流,再到最后的服务链路监控。
这些视频很少有告诉你为什么会这样做,只会告诉你这样做的好处,无法明白这些步骤在整个微服务生命周期中到底有什么作用,我就像个僵尸一样,别人说应该这样做,那就这样做吧,缺乏一些自己的思考。
向大佬学习
读书永远是学习门槛最低的,花费最少的,同时也是最有效的学习方法。怀着对微服务懵懵懂懂的感觉去找了在业界质量比较高的动物书系列中的一本比较经典的微服务书籍学习了下:微服务设计
这本书并没有如八股文似的明确告诉你什么是微服务,像包工头似的指挥你做什么,更多的是分享大佬自己的经验,用实际经验与读者交流探讨微服务到底做了什么,该如何设计微服务
学习总结
学习的思维导图:
接下来分享下自己从书中学习到的东西,以及一些自己的想法
概述
什么是微服务
内聚性
根据业务边界来确定服务的边界,保证每个服务具有单一职责原则,做到单个服务代码的内聚性
- 内聚性:把因相同原因而变化的东西聚合到一起,而把因不同原因而变化的东西分离开来
- 单个服务代码量:微服务并不是拆分的服务代码量越小越好,虽然拆分的
- 服务越小,独立性带来的好处越多,但是管理成本也会随之上升
- 最好就是单个服务刚好一个小团队可以维护即可
自治性
- 微服务通常会以分布式的方式部署在多台机器上,那么服务间的通信就很重要。
- 在设计一个服务对外提供的API时,应该考虑到什么该暴露,什么不该暴露。如果暴露的过多,就会导致服务消费方与API提供者产生耦合性,降低了服务的自治性。
- 一个好的自治性的服务的修改与部署,不应该影响其他任何服务
主要好处
技术异构性
微服务群上的每个服务并不一定要统一使用一种技术实现,对于不同服务选择最合适的才是最好的
- 得益于服务的自治性,可以在选择一个
风险最小的服务
上尝试新技术 - 由于技术选择的灵活性,可能会导致一个微服务团队需要使用多种技术栈,这将会增加团队的管理与维护。
弹性
- 单体服务:单体服务可以通过在不同的机器上部署,来提高服务的弹性
- 微服务:微服务本身就能很好的处理服务不可用和功能降级的问题。甚至以分布式的方式部署在不同的系统上
- 分布式系统:一旦部署分布式系统,就得考虑网络与机器的问题
扩展
- 得益于服务的拆分,可以只对需要扩展的服务进行扩展
简化部署
-
由于单个服务的代码量不大,以及与其他服务的耦合性低,当修改一个服务的代码,可以很简单的快速部署
这意味着微服务可以快速的进行功能迭代
与组织结构匹配
- 一个公司就是一个组织,每个公司的组织结构也不同,而我们编写的系统是为公司的组织服务的
- 微服务架构可以很好的将架构与组织结构相匹配,避免出现过大的代码库,从而获得理想的团队大小与生产力
可组合性与可替换性
- 底层业务API不变,BFF层可以灵活多变,适应不同的终端
- 随着公司组织或者业务的变更,可以很好的替换掉某个服务的某些代码,甚至替换掉整个服务
面向服务的架构SOA
-
可以认为微服务是SOA 服务的一种实现
-
难点:
实施SOA 最大的难点就是对服务的拆分粒度,通信协议的选择,第三方中间件的选择等:
-
到底拆分多小才算小,多大算大,目前没有所谓的标准, 如果一开始无法很清晰界定上下文的拆分,可以不用拆分的太细,=
并不是说一开始拆分为多少个服务,后续就一成不变的
-
但是一个好的微服务的架构并不是一开始就设计出来的,而是不断演进的
-
演化式架构师
架构师?
计算机行业发展不到百年,相比于其他传统行业,还是一个很年轻的行业。
架构师的职责:
- 架构师的一个重要职责是确保团队有
共同的愿景
,以帮助我们向客户交付想要的系统 - 根据不同层次的划分,有不同的架构师,包括系统架构师,业务架构师以及技术架构师。
软件工程师:
-
计算机行业的发展不到百年,相比于其他行业,还处于很年轻的状态
我们通常将自己称为软件
工程师
,但是业界却没有权威的认证,不像传统的建筑业有建筑师的认证,因此市面上的很多IT证书是没有意义的
类比建筑师
-
建筑师需要做好详细的计划,然后让别人去理解和执行
但是在软件行业,如果以建筑师的视角去当架构师,将会导致非常糟糕的实践
软件系统并不是一个设计好就一成不变的系统,他是
演进式
的,因此一个好的架构师的职责就是推进一个系统不断往好的方向演进
架构师的演化视角
软件是不断演化的,架构师应该尽量预期可能发生的变化,但是这个预测并不能做到面面俱到
- 架构师的职责之一就是把握软件演化的
大方向
- 保证该系统适合开发人员在其上工作,而不应该做过多的干预,让干工作人员像系统使用者一样
开心
架构师更多需要关注的是服务的边界
, 考虑服务之间如何交互,保证能够对整个系统的健康状态进行监控
技术架构师
- 作为技术架构师,服务的对象就是开发人员,为了了解自己设计的架构对开发人员是否友好,技术架构师应该经常抽时间和普通开发人员坐在一起工作,甚至可以结对编程
集中治理和领导
架构师的部分职责是治理
-
治理通过评估需求,保证企业目标的达成,通过排优先级和做决策来设定方向。并且对已经达成一致的方向和目标进行监督
-
最好的做法是架构师和开发小组一起交流讨论出治理方案,团队的力量永远大于个人
-
架构师对于团队的领导必须学会放手,给团队一定的自由
就好比教小孩子骑单车,必须学会放手,当驶向马路的时候,我们就要及时制止,也就是说要把握大方向
建设团队
对于技术领导人来说,更重要的是帮助你的队友成长
,帮助他们理解技术愿景
,并且积极地参与到愿景的实现和调整中来
原则与标准
战略目标
- 每个公司都有自己的战略目标,但是这些战略目标的层次都很高,通常不会涉及到技术层面,比如说“开扩东南亚市场”
- 而技术架构师就需要和业务部门交互,了解公司业务的愿景以及业务的演化,从而指定公司的技术愿景
原则
- 为了达成目标一致,往往会设计一些原则,当然这些原则并不是一成不变的
- 原则不宜过多,最好是可以在一张海报上清晰明了
实践
- 实践要基于原则,更加偏向技术层面,但是实践比原则更加灵活多变
- 实践包括代码规范,日志集中捕获,接口协议规范等
原则与实践相结合
要求的标准
每个公司都希望所有技术人员做到代码规范,很多公司都有自己的规范标准
- 为了使大家达成规范一致,一个好的做法是提供
服务代码模板
- 但是该模板必须是从真实运行代码中裁剪出来的
- 在裁剪代码模板时,一定要定义好该模板的职责,不能过于臃肿,毕竟模板是用来简化工作,而不应该使工作变得更加复杂
- 模板并不是共享依赖库,如果做成了依赖库,将会导致系统服务间的耦合
技术债务
-
技术愿景是为业务愿景所服务的,有时候当业务需要紧急特性上线时,技术不得不妥协,违背定下的一些原则与约束
-
对于创业公司来说技术债务会尤为显著,毕竟为了公司业务的快速发展,架构师与开发人员不得不妥协
但是要正视这些技术债务,它是一个公司发展所必经的旅途
架构师要做的就是要评估这些债务对系统的影响,然后提供一些温和的指导,让团队自行决定如何去偿还这些债务
-
和现实世界一样,欠的债必须还,即使还款速度很慢。
如果不偿还这些技术债务,随着这些技术债务的累积,系统必将处于奔溃的边缘
集成
寻找理想的集成技术
-
避免破坏性修改
尽量避免对一个服务的修改导致下游消费方也随之改变
-
保证API的技术无关性
不应该限制服务间通信的方式,因此保证服务间通信API与技术无关
-
服务易于消费方使用
-
隐藏内部实现细节
对消费方暴露的内部实现细节越多,服务间耦合性就越高
集成方式
-
共享数据库集成
相当于拆分了服务,但是使用同一个数据库来进行数据的通行,这种集成方式实现起来简单,但是耦合性也是最高的
-
同步与异步
-
该集成方式目的是隐藏服务的内部细节,使用通信来
协作
-
同步通信比较简单,很容易清楚整个业务流程,知道通信结果成功与否
异步通信对于运行时间长的任务来说比较有用
两者并没有好坏之分,合适的场景才是最好的
-
同步一般是请求/响应的方式,异步一般是基于事件的方式,基于事件的方式就可以很好的解耦服务与消费方
-
-
编排与协同
-
编排协作必须有一个大脑服务负责告知其他服务需要做什么,但是不需要知道怎么做的细节
缺点:
编排服务会导致以大脑服务为中心的网状服务,导致其他服务出现基于CRUD的贫血服务
-
协同一般是基于异步事件的方式,服务方不需要关心有哪些消费方,只需要发布事件至事件循环中,对应的消费者只需要订阅该事件即可
该协作方式可以很好的降低系统的耦合度
-
-
远程过程调用
优点:
- 可以快速生成服务端和客户端的桩代码
- 以普通方法的调用方式去调用远程服务API,而不需要知道其内部细节
缺点:
-
RPC的优点恰恰也导致了其缺点,快速生成桩代码的方式,导致了客户端与服务端的过渡耦合
服务端修改一个字段,客户端也得跟着修改一个字段,导致lock_step发布方式
-
因为使用方式太过简单,就像调用普通方法一样,很容易导致开发人员不知道是RPC调用还是调用的本地方法
-
因为RPC即使 隐藏了远程调用的复杂性,但其还是网络通信,网络通信是不可靠的,需要做一系列的处理
-
REST
REST可以作为RPC的替代方案,该风格强调的是资源的概念
- HTTP非常符合REST的实现,同时HTTP的大生态也非常丰富,包括缓存,负载,监控等插件
-
基于事件的异步协作方式
-
该方式需要考虑两点:服务如何发布事件机制,消费者如何接收事件机制
-
可以通过已有的消息代理中间件实现这种发布订阅模式
-
异步架构可以非常好的解耦服务间的耦合,同时也带来了挑战与复杂性
当在排查异步架构的问题时,需要使用异步模式的思维去思考
同时我们要确保异步的每个流程都有很好的监控,因此必须要有链路追踪监控的功能
-
-
响应式扩展
可以把多个调用的结果组装起来并在此基础上执行操作
该集成方式在分布式系统中使用的比较多
版本管理
-
尽可能推迟
减少破坏性修改影响的最好方法就是不修改
有时候产品与研发会因为一些
特殊的功能
导致需要修改服务,如果说这个功能是没必要的后者可以换种交互方式就可以做到不用发布新版本,作为开发人员其实是可以和产品磋商的,实在不行延迟发版也行 -
及早发现破坏性修改
一旦发现不可避免的破坏性修改,就要及时和收到影响的消费者服务的维护人员沟通同步,测试到位
-
使用语义化的版本管理
使用三个数字表示:例如1.3.0
- 1代表大版本号,如果升级为2,意味着和1版本不兼容了
- 3 代表增加功能或小升级
- 0代表修复漏洞
-
不同版本接口共存
有的客户端用户希望使用旧版本,有的有希望使用新版本的功能,并且这两个版本用的是同一份数据
这个时候就遇到了破坏性的修改
多个版本共存, 平滑迁移版本,最终在合适的时机弃用旧版本
如果使用的HTTP系统,可以在URL中加上版本号来区分
分解单块系统
原因
迭代速度
-
相比于多个团队维护一个巨大的单块系统,我想一个小团队维护一个拆分后的小系统更加轻松
在一个自治单元上的迭代将更加快速
团队结构
- 当团队结构分散各地,又需要同时维护一个单体系统时,将是十分痛苦的一件事
安全
-
由于安全审计的机制,很多敏感信息需要做严密的保护
将这部分业务的代码作为单独的服务分离出去,可以做到更好的监控、传输数据的保护和静态数据的保护
技术
-
拆分为多个服务后,在单个服务的技术迭代上将更加优雅简单
比如,如果一个系统的核心功能是推荐算法,并且该算法是需要不断迭代更新的,我们就应该将该算法的代码抽离为单独的服务,交给负责算法的团队维护
分解的方式
关键
-
寻找服务的边界,然后以增量的形式进行
秉承增量的分解方式,要先找到一个拆分点,然后不断地去削减单体服务
自下而上分解
-
从数据库开始分解
外键约束
:再分解数据库时会遇到外键的问题,我们应该放弃外键的约束,使用代码来实现这个约束
这种方式可能会导致服务间多次通信达到约束的效果,降低系统的响应速度
如果系统对响应速度要求不是太高,这种拆分数据库取消外键约束的方式是一种很好的方式
共享数据
:有时候一张表设计不合理包含了多个领域的字段
比如说为了方便动态修改客户的订单信息,客户表包含了仓库和财务的的字段信息
此时就需要用到领域的抽象方式,识别出客户的界限上下文,将该表抽象为财务,仓库和客户三个服务
-
自上而下分解的好处就是,消费者基本上是无感知的,并且可以随时选择回退或者继续修改而不影响外部服务的调用
自上而下分解
-
从服务开始分解
兼容旧数据
:从服务开始拆分,会出现为了兼容旧数据而写很多无意义的代码
影响消费者
:服务变更大概率会导致接口变更,直接影响到消费者
好处
:但是从服务开始拆分相比于从数据库开始拆分更加简单直观
事物与一致性
在未拆分前可以通过外键的约束或者在同一张表内来达成事务的一致性,在拆分为多张表后就被分离为了多个事务
-
最终一致性:
当出现了多个事务的时候,可以使用队列来记录事务先后顺序,当其中一个事务出现异常时,可以通过捕获异常,重试的方式来保证整个系统的一致性 -
终止整个事务
当事务的异常没办法导致重试时,需要发起补偿事务
也就是反向操作来重置整个系统的初始状态
简单来说比如执行了add异常,那就执行delete 抵消 -
分布式事务
可以利用分布式事务特性来保证整个系统的一致性
分布式事务使用两阶段提交
算法保证系统事务一致性,该算法有两个阶段:投票阶段与执行阶段- 投票阶段:
事务管理器会搜集所有参与者的投票,当出现一个否定的情况,就认定为失败 - 执行阶段:
会有一个中央协调进程来指挥参与者接下来的动作。
如果投票失败,中央协调者会告知所有参与者回退操作
如果成功,继续执行
缺点:
这种方式会导致参与者在投票完后暂停执行,一旦事务管理器宕机,整个系统将会暂停
并且协调进程会使用所,执行中的事务可能会对某些资源持有一个锁,导致后期系统难以扩展
- 投票阶段:
-
取舍
如果说系统对于实时性要求不高,建议使用最终一致性加事务补偿的方式来保证整个系统的一致性
报表
报表是对数据库中的数据的一种可视化操作,一般不包含太多的逻辑,使用SQL查询
但是报表的操作很依赖于数据库表结构,一旦表结构变更,可能会导致报表系统无法使用
调用服务获取数据
-
系统拆分后,不同数据保存在不同服务的表中,可以通过调用不同服务接口的方式来获取数据
但是一旦数据量过大或者访问频率高,这种方式的效率是很慢的
可以通过HTTP缓存或者批量请求来加速获取大文件
数据导出
-
可以将多个系统的数据导出到一个中央报表数据库,,然后使用视图之类的技术创建一个聚合。
导出数据的服务只需要知道自己的报表视图结构即可
部署
CI/CD
继续集成
好处
- 得到关于代码质量的某种程度的快速反馈
- 可以生成多个版本的构建物,并将其代码测试可视化
CI需要做什么
- 保证主分支代码持续集成
- 对每一次的集成是否有测试验收
- 构建失败后,是否会修复构建
每个微服务对应一个CI构建
流水线和持续交付
流水线
-
构建流水线将构建拆分为多个阶段,在每个阶段做不同的事情
比如说可以将测试拆分为快速测试阶段与耗时测试阶段,先运行快速测试阶段,如果说快速测试阶段失败了,就没必要继续运行了
持续交付
- 一个好的CD工具能够定义和可视化流水线,并对发布到生产环境的整个过程进行建模
测试
测试四象限
测试范围
- 金字塔从上往下测试范围越来越小,测试用例数量越来越多,测试细粒度越来越小
服务测试
服务测试实现起来比单元测试复杂,需要利用打桩或者mock
-
打桩:对于被测试服务的一个获取数据的透明服务,测试时不关心该打桩服务被访问了多少次
-
mock: 被测试服务也可以从mock 获取需要的数据,与打桩相比mock 会进一步验证请求本身是否被正确调用
端到端测试
端到端测试会包含多个服务的测试,测试范围更大,同时测试复杂度也最大,也最不利用定位失败的位置
不管是单元测试还是服务测试,或者是端到端测试,最好的做法都是使用流水线构建做到自动化测试
-
一种坏的流水线构建方式
- 直接将端到端测试放在一个服务构建流水线的最后,这种方式的端到端测试没法保证其他服务是可用的
-
比较好的做法
-
让多个流水线的服务扇入到一个独立的端到端测试的阶段
任意一个服务的构建都会触发一次端到端的测试
-
脆弱的测试
服务测试和端到端测试本身就是复杂的,容易失败的
包含在测试用的服务数量越多,测试就会越脆弱,不确定性也就越强
当脆弱性测试成为常态,测试人员可能就会对测试套件失去信心,认为这些失败是异常的正常化
服务测试套件应该也是迭代演化的,当一个服务测试不断失败的时候,我们就需要考虑该测试套件是否合理,然后暂时
将该失败服务测试从整个服务测试套件中移除
- 在修复这个服务测试后在重新加入,有时候可能会为了修复这个服务测试而需要改变被测试软件
谁来写测试
-
服务的测试是由维护服务的团队成员写,还是由专业的测试团队写
-
一个好的做法是共享端到端测试套件的代码权,但同时对测试套件联合负责
测试团队可以随意提交套件,但是实现服务的团队必须维护套件的健康
消费者驱动测试
-
替换端到端测试的一种方案
消费者编写测试用例,当服务发版不满足消费者测试用例时,认定服务有问题
监控
链路监控是微服务实践中最重要的环节之一
以前的单体服务,我们很直接的从单个系统日志中定位问题,但是拆分为微服务后,就会出现分布式部署的情况,有时候接口间的调用还是异步的,如果没有日志链路监控,排查问题将非常痛苦
目前市面上日志统一搜集与聚合可视化的工具已经比较成熟,logstash + kibana 就是一套标准的日志收集聚合显示的方案
但是日志链路监控的工具不是很多,相比于日志可视化没那么好用
日志链路监控的核心也是关联ID,需要有一个关联ID可以关联整个调用链路
安全
不管是单体服务还是微服务,服务安全都很重要
身份验证和授权
一些单体服务中使用的安全策略在微服务中同样是适用的,比如说秘钥验证,JWT token 验证等
静态数据的安全
可以通过加解密来保证静态数据的安全,但是一定不要自己造轮子,使用业界比较成熟的加密方式就可以了
深度防御
- 通过防火墙策略来过滤请求
- 对服务的关键操作进行日志记录,这样当出现一些非预期的操作出现时可以及时的发现
- 将不同的服务部署在不同的网络下
- 甚至可以使用比较老的操作系统,这也是我们经常看到一些安全性要求比较高的系统的桌面使用的都是比较旧的操作系统
康威定律和系统设计
康威定律
- 任何组织在设计一套系统(广义上概念上的系统)时,所交付的设计方案在结构上都与该组织的沟通结构保持一致
当协调变化的成本增加后,有一件事会发生:人们要么想方设法降低协调沟通成本,要么停止更改
而后者正是导致最终产生庞大的、难以维护的代码块的原因
- 一个团队有单个服务的所有权,将会使该团队对该服务更有责任感
内部开源
如果实在没办法让一个团队拥有单个服务的所有权,最好的做法就是使用内部开源的方式:
将开发团队分为核心提交者和代码守护者
代码守护者做的最多的就是审核MR的代码质量
规模化微服务
反脆弱组织
使用故障机器人猴子军队可以使你的服务更加健壮
- 混乱猴子: 在一天的特定时段随机停掉服务器
- 混乱大猩猩:随机关闭整个可用区的一部分
- 延迟猴子:在系统之间注入网络延迟
超时
-
如果等待太长时间来决定调用失败,整个系统会被拖慢
如果超时太短,会将一个可能还在正常工作的调用错认为是失败的
如果完全没有超时,一个宕掉的下游系统可能会让整个系统挂起
断路器
-
当请求下游失败达到一定阈值后,会触发断路器,认定下游服务出现故障,此时会断开与下游的连接,接下来的请求会快速的失败
客户端会发送偶尔健康检查,请求查看下游是否已经回复
如果已经恢复会重置断路器,恢复正常连接
舱壁
- 故障隔离:尽量为每个下游连接建立不同的连接池,这样当一类连接出问题时不会影响其余的连接
- 减载:实现拒绝请求的舱壁,以避免资源达到饱和
扩展
扩展原因
- 帮助处理失败,不将鸡蛋放在同一个篮子里
- 性能扩展,处理更多的负载,减少延迟
加机器
- 使用云厂商提供的ECI可以很好的对机器进行扩容或增加
拆分负载
- 将不同的服务部署在不同的主机上
分散风险
- 云厂商也不能保证其提供的服务是100%安全的,因此要考虑是否将重要服务部署在不同云上
负载均衡
-
包括硬件与软件层面的负载均衡,代价不同,各有优缺点
硬件价格高,容易出现单点故障,但是效果更好
软件可以将所有微服务都放在一个VLAN(虚拟局域网)中,然后对外提供一个统一的SSL请求入口
基于worker 的系统
-
拆分为基于worker的系统也可以很好的实现实例的扩展
但是需要一个可靠的消息队列,例如zookeeper 和MQ
自动伸缩
-
在未负载伸缩时,一定谨慎不要太仓促缩容
在大多数情况下,手头有多余的计算能力,比没有足够的计算能力要好得多
CAP定理
一致性(consistency)
- 当访问多个节点时,能达到同样的值
可用性(availability)
- 每个请求都能获得响应
分区容忍性(partition tolerance)
- 集群中的某些节点在无法联系后,集群整体还能继续进行服务的能力
在分布式系统中,最多满足CAP中的两个
AP系统
- 放弃一致性,保证分区容忍性和可用性的做法,被称为最终一致性
CP系统
- 牺牲可用性,保证系统一致和分区容忍
- 在这种模式下,服务必须考虑如何做功能降级,直到分区恢复以及数据库节点之间可以重新同步
AC系统?
- 如果系统没有分区容忍性,就不能跨网络运行,所以CA系统在分布式系统中根本不存在
使用CP还是AP?
- 对数据不一致的容忍性有多大?可以容忍多长时间的数据不一致性?
服务注册与发现
-
比较成熟的服务注册与发现的工具有:
Zookeeper, Consule, Eureka
文档服务
swagger
- 对超媒体接口支持不好
HAL和HAL浏览器
- 超文本应用程序语言是一个标准,用来描述公开的超媒体控制的biaozhun
总结
这本书并没有讲解微服务具体的实现细节,而是站在更高的角度去探讨微服务到底应该做什么?
也没有明确的说明什么叫微服务,而是明确的指出微服务架构应该是一个演进式的架构,我们要做的就是拥抱变化持续演进。
这本书花了很多的篇章去讲解服务拆分相关方面的知识,其中涉及到了很多领域驱动涉及方面的知识,作者并没有细讲DDD方面的内容,而是推荐读者去读DDD相关方面的书籍,但是却一直强调界限上下文的重要性,这是拆分服务的第一步,也是最难和最重要的一步。
这本书的后半部分则着重强调CI/CD工具对微服务的重要性,这个确实很重要,不然微服务一旦达到一定规模就是灾难。
如果系统没有分区容忍性,就不能跨网络运行,所以CA系统在分布式系统中根本不存在
使用CP还是AP?
- 对数据不一致的容忍性有多大?可以容忍多长时间的数据不一致性?
服务注册与发现
-
比较成熟的服务注册与发现的工具有:
Zookeeper, Consule, Eureka
文档服务
swagger
- 对超媒体接口支持不好
HAL和HAL浏览器
- 超文本应用程序语言是一个标准,用来描述公开的超媒体控制的biaozhun
总结
这本书并没有讲解微服务具体的实现细节,而是站在更高的角度去探讨微服务到底应该做什么?
也没有明确的说明什么叫微服务,而是明确的指出微服务架构应该是一个演进式的架构,我们要做的就是拥抱变化持续演进。
这本书花了很多的篇章去讲解服务拆分相关方面的知识,其中涉及到了很多领域驱动涉及方面的知识,作者并没有细讲DDD方面的内容,而是推荐读者去读DDD相关方面的书籍,但是却一直强调界限上下文的重要性,这是拆分服务的第一步,也是最难和最重要的一步。
这本书的后半部分则着重强调CI/CD工具对微服务的重要性,这个确实很重要,不然微服务一旦达到一定规模就是灾难。
接下来我将系统的学习k8s 相关方面的知识,去探索微服务在云原生舞台上的表现。