微服务设计学习(一)关于微服务和如何建模服务

前言

随着互联网在21世纪初被大规模接入,互联网由基于流量点击赢利的单方面信息发布的Web 1.0业务模式,转变为由用户主导而生成内容的Web 2.0业务模式。因此,互联网应用系统所需处理的访问量和数据量均疾速增长,后端技术架构也因此面临着巨大的挑战。

Web 2.0阶段的互联网后端架构大多经历了由All in One的单体式应用架构渐渐转为更加灵活的分布式应用架构的过程,互联网开发架构开始追求更高的质量和效率。

随着智能手机的出现以及4G标准的普及,互联网应用由PC端迅速转向更加自由的移动端。移动设备由于携带方便且便于定位,因此在出行、网络购物、支付等方面彻底改变了现代人的生活方式。在技术方面,为了应对更加庞大的集群规模,单纯的分布式系统已经难于驾驭,因此技术圈开启了一个概念爆发的时代——SOA、DevOps、容器、CI/CD、微服务、Service Mesh等概念层出不穷,而Docker、Kubernetes、Mesos、Spring Cloud、gRPC、Istio等一系列产品的出现,标志着云时代已真正到来

本文(或者说本系列文章),是本人在阅读完 Sam Newman 的《微服务设计》一书之后,与其他的微服务设计相关文章、《从服务化到云原生》等书籍进行关联阅读后做的笔记总结。

目的是构建分布式、微服务、云原生方面的体系化的知识结构树。

希望巩固学习的同时能够帮助到你。

一、关于微服务

1.1 什么是微服务

微服务就是一些协同工作的小而自治的服务。

关键词: 小而自治

“小”

“小”这个概念,一方面体现在微服务的内聚性上。

  • 内聚性也可以称之为单一职责原则:“把因相同原因而变化的东西聚合到一起,而把因不同原因而变化的东西分离开来。
  • 也就是说,微服务应该专注于做好一件事情。
  • 由业务边界来确定服务的边界

另一方面体现在代码库的大小,这里有几个参考的标准或者说原则

  • 代码库小到团队结构相匹配
  • 代码库小到易于迅速重写
  • 辩证的看待。服务越小,微服务架构的优点和缺点也就越明显

自治

“自治”这个概念,强调的是,一个微服务就是一个独立的实体。体现在服务之间的松耦合上。

  • 黄金法则:你是否能够修改一个服务并对其进行部署,而不影响其他任何服务?

关键点:要学会正确的建模服务,正确的设计服务API,才能做到上述两点。

1.2 微服务的好处

微服务的大多好处都适用于分布式系统架构,只不过微服务会将这些好处推向极致
  • 技术异构性

    • 不同服务根据业务场景、性能要求、功能需求采用不同的技术架构
    • 新技术的快速实践,技术团队的快速成长
  • 弹性/反脆弱性(anti-fragility)

    • 服务降级
    • 服务容灾、服务熔断
  • 扩展

    • 传统单体系统,无法做到对局部功能进行扩展
    • 根据具体的业务需求,对特定的微服务进行扩展
    • 通过架构的手段,节省成本
  • 简化部署

    • 传统单体应用,即使是一行代码修改,也需要整体重新部署。风险太大。
    • 微服务架构,各个服务部署相互独立

      • 灵活的发版方式
      • 快速回滚
      • 风险小
  • 架构与组织结构相匹配

    • 关联知识点:康威定律
  • 服务的可重用、可组合
  • 服务的可替代性,快速重写

1.3 面向服务的架构

SOA(Service-Oriented Architecture,面向服务的架构)是一种设计方法,其中包含多个服务,而服务之间通过配合最终会提供一系列功能。一个服务通常以独立的形式存在于操作系统进程中。服务之间通过网络调用,而非采用进程内调用的方式进行通信。

就像认为 XP 或者 Scrum 是敏捷软件开发的一种特定方法一样,微服务架构是 SOA 的一种特定方法

实施SOA会遇到的问题:

  • 通信协议(SOAP or REST)
  • 第三方中间件选型
  • 服务粒度划分
  • ......

思考与小结

微服务确实有许多优点:“反脆弱性(anti-fragility)”、容错、独立部署与扩展、架构抽象、技术隔离。但并不是说采用了微服务就自然地具备了这些特性。

比如,要具备反脆弱性,需要充分考虑分布式系统的不确定性,清楚异步、网络划分、节点故障、平衡可用性与数据一致性等问题

同样地,要具备可维护性和可扩展性,首先要有恰当的基础设施和组织结构

理论上讲,微服务可以提高开发速度,但在创建组织依赖时,“微服务佣金(MicroservicePremium)”可能会降低开发速度。

所以,采用微服务架构需要具备一些先决条件,包括恰当的持续发布管道、能胜任的DevOps 和Ops 团队、审慎的服务边界等等。此外,周密的测试和集成模式也很重要。

就书中这章最后一讲说的:微服务不是银弹,你需要在部署、测试和监控等方面做很多的工作。你还需要考虑如何扩展系统、并且保证他们的弹性,甚至还需要处理类似分布式事务、CAP相关的问题。

我觉得,这也是为什么服务化到云原生是大势所趋,因为只有结合“容器 +编排调度”的云平台,微服务才能将自己的优点发挥到最大。至于云原生的知识,又是后面的内容了。

引申阅读 Martin Fowler大神的文章

微服务佣金 https://www.martinfowler.com/...

二、如何建模服务

还是要重申两个重要概念,高内聚和松耦合,对应前面的关键词:小而自治

2.1 几个概念

限界上下文

此处作者引用了 Eric Evans 的著作《领域驱动设计》中的概念(这本书强烈建议阅读):限界上下文

任何一个给定的领域都包含多个限界上下文,每个限界上下文中的东西(Eric 更常使用模型这个词,应该比“东西”好得多)分成两部分,一部分不需要与外部通信,另一部分则需要。每个上下文都有明确的接口,该接口决定了它会暴露哪些模型给其他的上下文。
使用细胞作为比喻: “细胞之所以会存在,是因为细胞膜定义了什么在细胞内,什么在细胞外,并且确定了什么物质可以通过细胞膜。”

共享模型和隐藏模型

同时又提到共享模型和隐藏模型的概念。

共享模型就是上述比喻中上下文之间交互的模型,隐藏模型就是不需要与外部进行交互的模型。


关于如何开始微服务,作者在书中的观点和同在TW的Martin Fowler是一个观点:"MonolithFirst" - 单体应用先行。

主要出于以下考虑:

  • Yagni 原则——确定软件思路是否有用,最好的方法是创建一个简化版本,然后看它的使用效果。在这个阶段,最重要的是速度,而该原则可缩短反馈周期,避免微服务佣金。
  • 明确的有界上下文集合——只有服务存在良好且稳定的边界,微服务才能有效地发挥作用。但是,任何微服务间的功能重构都比在单体架构中难度大,即使是经验丰富的架构师在自己熟悉的领域里,也很难在一开始就恰当地定义出边界,而首先构建一个单体应用有利于明确功能边界。
引申阅读 https://www.martinfowler.com/...

当然这和他们所处的公司业务环境肯定有很大的关系,ThoughtWorks 是一家帮助其他公司解决问题的顾问公司,也就是说,他们会在某个公司的单体应用出现问题时提供帮助,将其重构为微服务架构。得出这样的结论也无可厚非。业界关于这个也有其他的声音,比如直接就从微服务开始。

我本人是比较倾向于这种方式,所以对这种方式进行了摘录和学习。

2.2 建模要点

  • 切忌过早划分

    过早将一个系统划分成为微服务的代价非常高,尤其是在面对新领域时。很多时候,将一个已有的代码库划分成微服务,要比从头开始构建微服务简单得多。

  • 确定限界上下文

    使用模块对限界上下文进行建模,同时使用共享和隐藏模型。

  • 从业务功能入手

    思考限界上下文的时候,应该从业务功能入手,首先要问自己“这个上下文是做什么用的”,然后再考虑“它需要什么样的数据”。

  • 逐步划分上下文

    当考虑微服务的边界时,首先考虑比较大的、粗粒度的那些上下文,然后当发现合适的缝隙后,再进一步划分出那些嵌套的上下文。

    • 嵌套上下文

    • 顶层上下文

思考与总结

如何在问题空间中寻找能达到高内聚低耦合的接缝。限界上下文是寻找这些接缝的一个非常重要的工具,通过将微服务与这些边界相匹配,可以保证最终的系统能够得到微服务提供的所有好处。

这一部分可以关联学习DDD理念相关书籍。

你可能感兴趣的