《微服务设计》读书笔记

📖阅读的目的

微服务是一种分布式系统解决方案,最近几年工作中使用的是微服务架构来部署服务,但自己接触到的主要是业务开发相关的工作,对微服务的了解主要偏实战方面,而对于构建、集成、分解、测试、部署、监控、架构演进等相关内容没有系统性的了解过,此书内容比较全面,包含了微服务设计的各种主题,读这本书主要希望可以系统性的了解一下微服务的方方面面。

⚓️本书的整体框架

这本书主要基于主题来组织内容,主要包含以下主题:

  1. 微服务基本概念的介绍,
  2. 如何构建微服务,
  3. 什么样的服务集成技术对微服务最有帮助,
  4. 如何把一个大的单块系统分解成微服务,
  5. 如何部署微服务,
  6. 如何测试微服务以确保软件质量,
  7. 对于复杂的分布式系统如何监控,
  8. 如何安全的使用微服务,
  9. 使用康威定律解释开发人员组织结构和系统设计的相互租用,
  10. 介绍规模化后微服务面临的问题以及符合应对问题。

这篇文章只是选取书中部分观点拿来讨论,不是总结和概括。

本书的目录

微服务设计.png

微服务定义

对于微服务,作者定义为一些协同工作的小而自治的服务,“小而自治”可以使用单一职责原则来解释:把因相同原因而变化的东西聚合在一起,而把因不同原因而变化的东西分离开。这个原则也可以用来指导单个服务的微服务拆分。

多小算小

澳大利亚RealEstate.com.au的Jon Eaves认为,一个微服务应该可以在两周内完全重写。服务是否够小,作者认为需要考虑以下因素:

  1. 服务越小,微服务架构的优点和缺点也就越明显
  2. 微服务越小,独立性带来的好处就越多,但也就越复杂
  3. 如果开发者不再觉得代码库过大,那就可以认为足够小了。

自治:

一个微服务是一个独立的实体,独立部署,服务之间通过网络调用进行通信,从而加强服务之间的隔离性,避免耦合。

微服务的优点:

  1. 技术异构性:因为单个微服务力度足够小,在由多个微服务组成的系统中,可以在不同的微服务中使用不同的技术,比如使用不同的语言、框架、不同的数据库等。
  2. 弹性:微服务可以部署在多个机器上来降低功能完全不可用的概率,这样当一个服务不可用时也可以避免级联故障的产生。
  3. 扩展:可以对特定的模块进行扩展或缩容,比如性能要求高的部署在性能好的机器上,性能要求低的部署在性能稍差的机器上
  4. 简化部署:部署时只需要部署修改的部分而不是把整个大的服务。
  5. 与组织架构相匹配:不同模块由不同的人员维护开发
  6. 可替代性:对于大的服务,重构替代比较难,但是微服务就相对简单,可能只需要几天就能完成。

微服务虽然好处很多,但是微服务并不是没有缺点,更不是银弹,使用微服务之前需要考虑清除。

架构师

架构师的一个重要职责是确保团队有共同的技术愿景,以帮助我们向客户交付他们想要的系统。

作者有一个观点特别有意思,他认为架构师是参考其它行业比如建筑师来命名的,但是“架构师”并不需要像“建筑师”那样需要对设计保证足够的精确,且对产物负有不可推卸的责任,但是软件“架构师”却需要保证软件有足够的灵活性和适应性,并且能够根据用户的需求进行演化。这么看来,软件设计师更像是城市规划师,只需要保证大方向上的正确,对于模块内的具体设计可以随机应变。

指导原则

软件设计的关键是取舍,而哪些取哪些舍就需要满足一些原则,而原则本身也需要取舍,最好不要超过10条,否则当原则太多可能会产生冲突也不便记忆,可以参考【1】 https://www.12factor.net/zh_cn/ 的12项原则:

I. 基准代码

一份基准代码,多份部署

II. 依赖

显式声明依赖关系

III. 配置

在环境中存储配置

IV. 后端服务

把后端服务当作附加资源

V. 构建,发布,运行

严格分离构建和运行

VI. 进程

以一个或多个无状态进程运行应用

VII. 端口绑定

通过端口绑定提供服务

VIII. 并发

通过进程模型进行扩展

IX. 易处理

快速启动和优雅终止可最大化健壮性

X. 开发环境与线上环境等价

尽可能的保持开发,预发布,线上环境相同

XI. 日志

把日志当作事件流

XII. 管理进程

后台管理任务当作一次性进程运行

列原则简单,但要和实践相结合才好。

什么样的服务是好服务

作者给出的两个概念是:1、松耦合;2、高内聚。这两个概念也不仅仅是微服务的设计理念,而是所有系统设计的基本要求。

做到松耦合,在修改一个服务的时候就不需要修改另一个服务,这样就能够做到独立部署一个服务而不需要修改系统的其它部分。

做到高内聚,也就能在需要修改一个功能时只需要修改一个服务就能实现需求。

可见,松耦合和高内聚本质上可以达到相同的目标。

不要过早划分服务

在服务有明确的边界之前,最好不要划分服务。毕竟拆分服务比把服务合并起来更容易一些。当一个服务业务边界逐渐明确时,再根据业务边界逐步拆分服务。

对于单个大服务的分解,也建议从分解数据库开始,将杂乱的依赖理清。

服务的集成

多个服务的集成有多种方式,比如共享数据库、REST调用、远程过程调用。同时服务间调用也有同步调用和异步调用两种方式。这两种方式各有各的好处,不同场景可能需要选择不同的调用方式。

如果使用同步服务,发起一个调用后调用方会阻塞自己并等待整个操作的完成;如果使用异步通信,调用方不需要等待操作完成后就可以返回,甚至可能不需要关心这个操作是否完成。采用异步的方式就需要保证异步调用的可靠性(比如失败了怎么处理,异步任务需要保证幂等)。

服务部署

服务拆分后,服务的数量可能会是原来的几倍、几十倍,可能一个需求的改动会设计几个或者更多的服务部署,这时服务的部署就会变成一个无法避免的问题。一个比较好的做法是将持续集成映射到服务,在代码修改后通过配置自动部署。这里有一个需要注意的点就是可能需要对不同的服务定制化不同的镜像,docker是一个很好的选择。

测试

《敏捷软件测试》一书曾把测试分为以下四个象限。

测试的象限.jpeg

处于象限底部的是面向技术的测试,即那些首先能够帮助开发人员构建系统的测试。这个象限中的测试通常是可以自动化的,比如性能测试和单元测试(关于单元测试可以参考这篇文章《学习单元测试,告别祈祷式编程》【2】https://mp.weixin.qq.com/s/oD96OEv92oX0ypAYLbYFyA)。

处于象限上方的测试则是帮助非技术背景的相关人群,了解系统是如何工作的。这种测试包括象限左上角的大范围、端到端的验收测试,还有象限右上角的由用户来进行的在UAT系统上进行手工验证的探索性测试。

测试是微服务系统的一个关键步骤,如果在微服务系统中还有大量的手工测试,可能让系统稳定运行会变成一个挑战。

《Scrum敏捷软件开发》中提到了测试金字塔的概念,测试金字塔如下所示

测试的范围.jpeg

主要由单元测试、服务测试和用户界面测试三层。这张图和上一张象限图有异曲同工的作用,都是将测试分为多个层。

监控

有过bug修复经验的人都知道,在只有一个服务的时候,监控是相对简单的,遇到问题只需要到服务所在容器或者机器查看错误即可。但如果系统是微服务架构,特别是调用链有多个节点时,定位错误就变成了一个不可能完成的任务。此时,监控工具就变得尤为重要。

日志、全链路追踪工具是一个好的选择。

安全

对于微服务的安全,完全同意作者的观点

  1. 不要实现自己的加密算法。不要发明自己的安全协议。
  2. 不要实现自己的加密算法。不要发明自己的安全协议。
  3. 不要实现自己的加密算法。不要发明自己的安全协议。

重要的事情说三遍。

康威定律

梅尔 ·康威于1968年4月在Datamation杂志上发表了一篇名为“How Do Committees Invent”的论文,文中指出:

任何组织在设计一套系统(广义概念上的系统)时,所交付的设计方案在结构上都与该组织的沟通结构保持一致。

这句话被称为康威定律。可以用埃里克 · S.雷蒙德在《新黑客字典》中定义总结:“如果你有四个小组开发一个编译器,那你会得到一个四步编译器。”

比如,如果一个组织的耦合度非常低,其创建的系统的模块化就越好,耦合也越低;组织的耦合度越高,其创建的系统的模块化也越差。

康威定律主要强调系统设计和组织结构不匹配可能会导致危险,这引导组织将服务所有权与团队相匹配。

规模化

一旦规模化之后,服务就会不可避免的出现问题,现在没有任何一个服务敢保证自己的服务100%可用, 99.999%可用性 已经是一个了不起的数据(但即使这样当服务超过10w时,也总有一台机器是不可用的)。所以,规模化后,即使你买最好的工具,最昂贵的硬件,也无法避免它们会发生故障的事实。

与其把时间放到如何避免服务出错还不如把时间放到如何快速修复系统上。

CAP定理

分布式系统中有三方面需要彼此权衡:一致性(consistency)、可用性(availability)和分区容忍性(partition tolerance)。具体地说,这个定理告诉我们最多只能保证三个中的两个。

具体参考:阮一峰《CAP 定理的含义》【3】https://ruanyifeng.com/blog/2018/07/cap.html

其它有意思的事情

“两个披萨团队”(没有一个团队应该大到两个比萨不够吃)。

如果不知道怎么拆分微服务,就先构建单个服务吧。

总结

微服务的原则.jpeg

不要实现自己的加密算法库。也不应该实现自己的分布式协调系统。使用已有的可工作的选择是非常明智的。

参考链接

  • 【1】https://www.12factor.net/zh_cn/
  • 【2】《学习单元测试,告别祈祷式编程》【https://mp.weixin.qq.com/s/oD96OEv92oX0ypAYLbYFyA
  • 【3】《CAP 定理的含义》https://ruanyifeng.com/blog/2018/07/cap.html

最后,感谢女朋友支持和包容,比❤️

也可以在公号输入以下关键字获取历史文章:公号&小程序 | 设计模式 | 并发&协程

扫码关注

内推时间