第1章-微服务<br>
什么是微服务
1. 很小,专注于做好一件小事
通常通过创建一个抽象层或者模块来保证代码的内聚性
对外提供一个简单的API接口,逻辑的复杂性在内部解决
单一职责原则
微服务将单一职责原则应用到服务上,根据业务边界来确定服务边界
多小是合适的?
服务越小,微服务架构的优先和缺点越明显
优点:开发灵活,速度快等等
缺点:管理维护复杂等等
2. 自治性
对外提供一个简单的API接口,逻辑的复杂性在内部解决
服务的发布更新不会影响到调用方
主要好处
1. 技术异构性
支持不同的技术栈,更好的适应不同的场景
6. 可组合性
每个微服务都是一个小功能
多个微服务组合成一个大功能
7. 对可替代性的优化
微服务足够小,重构or新技术重写速度快,影响面小
面向服务的架构SOA
作者认为微服务是SOA的一个具体实现例子
没有银弹
微服务架构并不是通用解决方案,不能解决任何技术问题
第2章-演化式架构师
不同之处
软件架构师面对的需求不固定,并且经常变更,必须要适应这种变更
其他架构师(例如,建筑师)需求固定,设计好之后不会再变更
架构师的演化视角
必须改变那种从一开始就要设计出完美产品的想法
我们应该设计一个合理的框架,在这个框架下慢慢的演化出正确的系统
软件架构师的一个职责是:保证该框架是适合开发人员在上面工作的
划分模块
作为软件架构师,不应该过多的关注每个模块内细节,而是要<font color="#c41230">关注模块之间如何交互</font>
一个原则性的方法
领导者确定公司<font color="#c41230">战略目标</font>
架构师根据战略目标确定具体的系统架构<font color="#c41230">原则</font>
原则不能太多(不超过10个),否则没人能记住
架构师确保程序员在<font color="#c41230">实践</font>时遵从<font color="#c41230">原则</font>
代码治理
架构师提供范例和服务代码模板
让程序员看文档的难度远远大于看代码
程序员都是懒惰的,能copy就不会自己写
例外管理与技术债务
在一些情况下,会偏离指导原则,这是无法避免的
指导原则不适应变化,此时要参考现实情况,做优化升级
指导原则没有问题,此时就带来了技术债务
架构师维护一个债务列表,并提供温和的指导,然后让程序员自行决定如何偿还这些技术债务
集中治理和领导
架构师的部分职责是治理
确保大方向正确,小方向由各个程序员自己把控
第3章-如何建模服务
限界上下文(bounded context)
任何一个给定的领域都包含多个限界上下文
每个限界上下文中的模型分为两种
不需要与外部通信
需要与外部通信
每个限界上下文都有明确的接口,该接口决定了它会暴露哪些模型给其他的限界上下文
避免过早服务拆分
如果服务之间的边界搞错了,后面修复的代价会很大
最好能够等到系统稳定下来之后,再确定把哪些东西作为一个服务划分出去
业务功能
从业务功能角度来确定限界上下文、划分服务是一个不错的选择
逐步划分上下文
先从单体系统,划分成粗粒度的上下文,然后在粗粒度的上下文里划分细粒度的上下文
不一定要一步到位,而且这么做大概率是失败的
组织架构和软件架构是相互影响的
不同团队之间的沟通协调是一个大问题
关于业务概念的沟通
对于某个功能所要做的修改,就更倾向于局限在一个单独的微服务边界之内
减小了修改的范围,并能够更快地进行部署
第4章-集成
寻找理想的集成技术
避免破坏性修改
对某个服务做的一些修改不应该会导致该服务的消费方也随之发生改变
使你的服务易于消费方使用
使用客户端库对于消费方来说很方便,但是会造成耦合的增加
隐藏内部实现细节
共享数据库
最快最流行的集成方式,但不是一个好的方式
这使得外部系统能够查看内部实现细节,并与其绑定在一起
最终导致:低内聚,高耦合
通信模式:同步与异步
具体场景决定采用哪种方式
同步方式
RPC(远程过程调用)
RPC的核心想法是隐藏远程调用的复杂性
异步方式
实现基于事件的异步协作方式
主要有两个部分需要考虑:微服务发布事件机制和消费者接收事件机制
尽量让中间件保持简单,而把业务逻辑放在自己的服务中
异步架构的复杂性
编排(orchestration)与协同(choreography)
使用编排(orchestration)的话,我们会依赖于某个中心大脑来指导并驱动整个流程,就像管弦乐队中的指挥一样
使用协同(choreography)的话,我们仅仅会告知系统中各个部分各自的职责,而把具体怎么做的细节留给它们自己,就像芭蕾舞中每个舞者都有自己的方式,同时也会响应周围其他人
子主题
服务即状态机
响应式扩展
微服务世界中的DRY和代码重用的危险
在微服务内部不要违反DRY,但在跨服务的情况下可以适当违反DRY
客户端库
对于微服务架构来说,客户端库必须有类似服务发现、故障模式、日志等方面的工作,来提升服务开发的效率。否则,采用微服务架构首先会带来极大的开发量,明显降低开发效率。
按引用访问
讨论的是:数据实体的有效性问题(是否过期)
版本管理:如何做微服务的版本升级
使用语义化的版本管理
语义化版本管理的每一个版本号都遵循这样的格式:MAJOR.MINOR.PATCH
MAJOR的改变意味着其中包含向后不兼容的修改
MINOR的改变意味着有新功能的增加,但应该是向后兼容的
PATCH的改变代表对已有功能的缺陷修复
不同的接口共存
新版本在新接口上,老版本在老接口上,让调用方慢慢从老接口迁移到新接口上,待迁移完,即可下掉老接口,完成版本升级
同时维护两个接口期间,可以让老接口调用新接口,来提升开发效率
同时使用多个版本的服务
新版本在新服务上,老版本在老服务上,让调用方满门从老服务迁移到新服务上,待迁移完成,即可下掉老服务,完成版本升级
同时维护两个服务期间,可以让老服务调用新服务,来提升开发效率
用户界面
APl组合
倾向于把API设计得比较细粒度化
API入口(gateway):将多个底层的调用会被聚合成为一个调用
界面调用API入口(gateway)
Ul片段的组合
界面由多个块组成,每个块调用不同的API入口(gateway)
一个块由一个团队负责,从前端到后端,减少沟通的代价
为前端服务的后端BFF(Backends For Frontends)
使用服务端的聚合接口或API入口
可以对多个后端调用进行编排,并为不同的设备提供定制化的内容
与第三方软件集成
应该自己做,还是买?
对于一般规模的组织来说,如果某个软件非常特殊,并且它是你的战略性资产的话,那就自己构建;如果不是这么特别的话,那就购买
CMS
Content Management System:内容管理系统
CRM
Customer RelationshipManagement:客户关系管理
小结:最大程度地保证微服务之间的低耦合
无论如何避免数据库集成
第5章-分解单块系统
关键是接缝
从接缝处可以抽取出相对独立的一部分代码,对这部分代码进行修改不会影响系统的其他部分
识别出接缝不仅仅能够清理代码库,更重要的是,这些被识别出的接缝可以成为服务的边界
杂乱的依赖
数据库是所有杂乱依赖的源头
通过API来访问,而不是直接访问数据库
对性能表示担忧问题
思考一个问题:你的系统需要多快?系统现在是多快?
一部分变慢会带来更大的好处,尤其是当这个“慢”事实上还在可接受的范围内时
共享数据:特点是数据可变
抽象出一个单独的服务处理共享数据
事务边界
若某个API出现失败了,事务如何处理??
终止整个操作
分布式事务
避免自己去创建这套API
尽量使用现有的实现
所有这些方案都会增加复杂性
如果你遇到的场景确实需要保持一致性,那么尽量避免把它们放在不同的地方,一定要尽量这样做
否则,尝试转变为:最终一致性
创建一个概念来表示这个事务
举个例子,你可以创建一个叫作“处理中的订单”的概念,围绕这个概念可以把所有与订单相关的端到端操作(及相应的异常)管理起来
将数据库里的事务转变到代码中来保证
报表数据库的问题
通过服务调用来获取数据
只适合一个非常简单的报表系统
数据导出
一个cron任务,定时从库中导出数据,再导入到同步库中
报表系统表结构的耦合的问题
可以创建一个大视图来做数据聚合:大宽表,导入和导出只对大宽表做
事件数据导出
在事件发生时就给报表系统发送数据,而不是靠原有的周期性数据导出,时效性高
数据导出的备份
第6章-部署
CI(Continuous Integration,持续集成)
测试是否真正理解CI的三个问题
是否每天签入代码到主线
是否有一组测试来验证修改
当构建失败后,团队是否把修复CI当作第一优先级的事情来做
把持续集成映射到微服务:三种模式
把所有微服务放在同一个代码库中,并且只有一个Cl构建
CD(Continuous Delivery,持续交付)
一个使用构建流水线建模的标准发布流程
与微保的工作环境对应关系
快速测试:DEV环境
耗时测试:SIT环境
用户验收测试:UAT环境
性能测试:PRE环境
生产环境:PRD环境
平台特定的构建物
Ruby中有gem, Java中有JAR包和WAR包,Python中有egg
通过自动化工具可以对不同构建物的底层部署机制进行屏蔽
使用OS特定构建物的好处是,在做部署时不需要考虑底层使用的是什么技术
从来没有遇到过这种部署方式
定制化镜像/容器部署方案
不可变服务
不用考虑OS的环境配置问题
需要注意:机器上的持久化数据也被保存到了其他地方
不同环境的管理是一个问题
服务配置
推荐的方案是:有一个专门的系统来提供配置管理=>配置中心
保证在CD流水线的构建物是同一个,而不是分TEST构建物和PRD构建物
服务与主机之间的映射
单主机多服务
运维团队的工作量通常与所要管理的主机量成正比
成本降低
主机的监控复杂
主机故障所造成的影响很严重
服务的部署也会变得更复杂
不利于团队的自治性
每个主机一个服务:推荐这种方式
带来了很多的主机管理问题,人工管理是不可取的,必须自动化管理