QCon 演讲火热征集中,快来分享技术实践与洞见! 了解详情
写点什么

微服务划分的模式与反模式

  • 2020-04-26
  • 本文字数:4168 字

    阅读完需:约 14 分钟

微服务划分的模式与反模式

微服务划分模式

虽然服务是逐步被拆分出来的,随着业务的演进,在某一时刻,可能需要我们重新审视服务划分得是否合理。本节向大家推荐两种服务划分的方法,首先介绍如何选择服务划分的方法。

基于业务复杂度选择服务划分方法

根据业务复杂度划分服务,如图 2-4 所示。当业务复杂度足够高的时候,应该基于领域驱动划分服务,而领域驱动本身足够复杂,很多概念比较抽象,应用范围并不是特别广泛,所以当业务复杂度较低时,可以选择基于数据驱动划分服务。数据驱动更容易理解和上手。也就是说,除非业务复杂度非常高,否则应该优先以数据驱动划分服务。这里的业务复杂度专指业务逻辑,而非数据量、并发量等相关复杂度。



图 2-4 根据业务复杂度划分服务


在做出选择的时候,还有一个参考指标是,团队以前是否已经基于领域驱动开发业务。也就是说,如果产品已经基于领域驱动开发了一段时间,团队具备了领域驱动开发的能力,那么推荐继续选择领域驱动划分服务。如果是一个全新的产品,则可以灵活选择。


选择服务划分的方法时要重点考虑如下条件。


  • 业务复杂度。

  • 团队对领域驱动的熟悉程度。


基于数据驱动划分服务


现比较粗糙的界面,进行内部讨论;不断迭代此环节,直到满意为止。


(2)抽象数据结构。根据需求总结 Use Case,协助分析需求,从中抽象数据结构。


(3)划分服务。分析数据结构,识别服务——服务应该满足高内聚、低耦合、单一职责等特征。


(4)确定服务调用关系。先分析出主要流程,根据请求需要调用的服务确定服务调用关系。如果存在问题,则需要回到(1)重新开始。


(5)业务流程验证。重新回到 User Story,以服务为粒度实现时序图,注意此阶段重点是验证服务划分是否合适,要关注如下问题。


  • 一次更新操作如果要跨越更多服务,那么一致性的要求是什么。

  • 跨服务查询时,是否要做关联查询,一个服务内是否能解决问题。

  • 性能是否能满足要求。

  • 成本是否满足要求。

  • (6)持续优化。


基于领域驱动划分服务


领域驱动是一个自上而下的架构设计方法,通过和领域专家建立统一的语言,不断交流,确定关键业务场景,逐步确定边界上下文。领域驱动更强调业务实现效果,认为自下而上的设计可能会导致技术人员不能更好地理解业务方向,进而偏离业务目标。


通常基于领域驱动划分服务的步骤如下。


(1)通过模型和领域专家建立统一语言。建立统一语言是为了更深入地理解需求。通用语言尽量以业务语言为主,而非技术语言;通用语言和代码一样,需要不断地重构。


(2)业务分析。确定核心的业务流程,然后逐步扩展到全部。最好通过工具呈现比较粗糙的界面,供内部讨论。


(3)寻找聚合。显式地定义领域模型的边界。最近比较热门的事件风暴,是一种基于领域驱动分析业务、划分服务的方法。


事件风暴就是把所有的关键参与者都召集到一个很宽敞的屋子里来开会,并且使用便利贴来描述系统中发生的事情,如图 2-5 所示。



图 2-5 事件风暴


  • 用桔黄色的便利贴代表领域事件,在上面用一句话描述曾经发生过什么事情。

  • 用蓝色的便利贴代表命令。命令的发起者可能是人,也可能是注入系统中的外部事件,或者定时器等。

  • 用黄色的便利贴代表聚合。聚合是一组相关领域对象的集合,高内聚、低耦合是其基本要求,聚合内还要保证数据一致性。


(4)确定服务调用关系。先分析出主要流程,根据一次请求需要调用的服务来确定服务调用关系。如果存在水平划分,则需要根据服务依赖原则确定关系。如果存在问题,则需要回到(1)重新开始。


(5)业务流程验证。以服务为粒度实现时序图,注意此阶段重点是要验证服务划分是否合适,主要关注如下问题。


  • 一次更新操作如果要跨越更多服务,那么一致性的要求是什么。

  • 跨服务查询时,是否要做关联查询,一个服务内是否能解决问题。

  • 性能是否能满足要求。

  • 成本是否满足要求。


(6)持续优化。


从已有单体架构中逐步划分服务


在大多数场景下,并非从开始阶段就采用微服务架构,而是随着业务不断发展,从最初的单体架构中逐步拆分服务。下面描述了从一个单体架构逐步拆分的步骤。


(1)所有微服务成功的故事都是从一个单体架构太大,需要被拆散开始的,如图 2-6 所示。我们应该从单体架构开始,当系统规模足够大、团队人数足够多时,再逐步拆分服务,通常前后端分离是拆分的第一步。



图 2-6 从已有架构逐步拆分服务(一)


(2)提取公共基础服务,如单点登录。拆分可以遵循逻辑分离和物理分离两种方法。另外随着系统压力的增加,可能会用到消息中间件、分布式缓存等服务。


(3)不断地从老系统中抽象出服务,垂直划分优先,如图 2-7 所示。



图 2-7 从已有架构逐步拆分服务(二)


(4)当业务越来越复杂的时候,API Gateway 做了太多的事情,会成为一个瓶颈点,服务之间的依赖关系也会变得越来越复杂,此时,需要适当地进行水平切分,如图 2-8 所示。



图 2-8 从已有架构逐步拆分服务(三)


微服务拆分策略


当不断从单体架构中抽象服务的时候,哪些服务优先被拆分,哪些服务不需要被拆分?以下几个策略可以帮助解决拆分中的这些问题。


  • 比较独立的新业务优先采用微服务架构。从成本角度考虑,新业务采用新的架构是最合理的,因为这样做对老业务的影响最小。

  • 优先抽象通用服务。因为通常通用服务的边界比较明显,耦合度低,比较容易分离。

  • 优先抽象比较容易识别的、边界比较明显的服务。如果原有包结构比较清晰,可以基于原有包结构中有明显边界的、比较完整的业务进行划分,这是从成本角度考虑。如果已经基于单体架构开发了一段时间,对业务的理解程度已经非常高,那么开发及架构人员能够比较容易地提炼出一些边界比较明显的服务。

  • 优先抽象核心服务。因为微服务的开发及运维成本比较高,并不是所有的地方都需要划分很小的粒度。往往一些比较边缘的运营、管理的系统甚至不会考虑拆分。另外,随着时间的推移,有一些业务可能会发生改变,因此应该先抽象出核心服务。

  • 优先抽象具有独立属性的服务。应根据功能的变更频率、资源占用、技术栈等属性划分服务。

  • 采用绞杀者模式,在遗留系统外围,随着时间的推移,让新的服务逐渐“绞杀”老的系统。在这种情况下,复杂度往往体现在如何灰度发布、迁移数据,以及如何保障服务不中断,后面的章节会详细描述。


如何衡量服务划分的合理性


每个产品在实施微服务架构最初的动力都不一样,目标也有所区别,所以判断是否划分合理,首先要看是否达成了目标。其次,可以参考以下几种衡量方式。每种衡量方式不能单独作为一个判断标准,需要综合考虑。


  • 一个小功能的修改从需求到上线需要多长时间?正常情况下的微服务架构交付周期应该是以天为单位的。如果一个小功能的修改需要几周到几个月的时间,可能意味着服务划分粒度过大,存在太多的冲突,要等待合并代码。

  • 大多数功能修改是否可以在一个服务内完成?如果经常需要跨服务团队的联合开发组才能完成一个新功能的开发或者旧功能的修改,则说明服务划分存在问题。

  • 是否要频繁修改接口?频繁修改接口有可能是接口设计不合理导致的,也有可能是服务划分的问题导致的,说明服务之间的边界并不是特别明确和稳定。

  • 响应时间是否能满足要求?在某些追求极致性能的场景中,对响应时间要求较高,服务划分的层次太多、粒度太小都可能导致响应时间不能满足要求。

  • 是否存在大量的跨服务更新?是否存在大量的跨服务的关联查询?出现这两个问题,可能是因为划分不合理。

微服务划分反模式

前面我们介绍了如何划分服务,在此之上,我们希望通过微服务划分的反模式来帮助大家少走弯路。


根据代码行数划分服务


代码规模太大会导致沟通效率、交付效率低下,耦合度高,以及比较笨重。代码规模可以作为一个参考,但是不能作为一个绝对标准,微服务架构中存在一个“大服务”是很正常的。基于代码行数拆分服务很难衡量服务的完整性,容易导向更小的拆分粒度,引起不必要的复杂度。


划分粒度越小越好


服务的大小并不是特别重要,可以根据团队规模、代码规模、业务复杂度、技术领域、重要程度、成本等因素综合考虑。关于服务粒度的大小,业界并没有统一标准,也很难衡量,最接近的衡量标准是研发团队规模。粒度小意味着更高的维护成本。后端管理、辅助系统通常粒度较大。


一次性划分服务


拆分服务有如下两种方式。


第一种,先拆分业务代码再拆分数据库。如图 2-9 所示,数据库并没有拆分,只是从单体中抽象出部分服务。



图 2-9 先拆分业务代码再拆分数据库


第二种,业务代码和数据库同步拆分。如图 2-10 所示,部分业务服务被拆分出来的同时,数据库也被同步拆分出来。



图 2-10 业务代码和数据库同步拆分


采用第二种方式拆分服务时,根据服务将数据库彻底拆分为多个独立的数据库,每个服务独享数据库服务,服务之间只能通过接口调用。这看起来非常美好,但需要为此做大量的数据迁移。当业务处于初期,需求不是非常确定,开发人员对业务理解不是特别透彻的时候,可能拆分后发现拆分得并不合理,只能再进行合并,又要进行一次数据迁移。相对来说,业务代码拆分成本更低,而数据迁移的成本更高,频繁、大量的数据迁移并不可取。


更好的做法是把第一种方式作为过渡阶段,当业务逐步稳定后再彻底进行数据迁移。注意,处于过渡阶段时数据库并没有彻底分离,一切依赖都通过接口访问。但是这只是口头上的约定,对于业务开发人员直接在数据库中进行关联查询。需要通过 Code Review 的方式避免。


服务划分是一个长期的过程,需要积累大量的领域知识,以此来理解核心流程。最好是和领域专家一起组成联合团队,在理解核心问题的情况下,持续拆分服务并验证拆分合理性,随着时间的推移,还可以重新划分。可见,服务拆分是一个持续性的过程。


服务划分一旦完成,不能改变


由于业务的不断变化,以及开发人员对领域知识和其他影响因素的理解等问题,很难一次性做出一个完美的解决方案。通常在划分后会发现,某个问题是不可忍受的,例如划分后导致响应时间降低,增加了更多的成本,有可能需要重新合并服务;由于业务的变化,原本的依赖关系发生了变化,有可能面临需要重新划分服务等类似的问题。


**先实施组件化,再实施微服务架构 v


很多技术人员试图先通过组件化逐步过渡到微服务架构,这是一种错误的思路。微服务架构划分更强调业务领域的完整性,因此垂直划分优先,而组件化往往通过抽象出稳定的部分形成组件共享,对调用次数和依赖关系并不强调。因此,组件化之后再转化到微服务架构的方式,通常是错误的。


本文转载自技术琐话公众号。


原文链接:https://mp.weixin.qq.com/s/EM98g6EdM2tVzUGiuuSBow


2020-04-26 16:441884

评论

发布
暂无评论
发现更多内容

在API 接口的设计中数据的安全性和完整性,该如何保证?

伤感汤姆布利柏

Code Review:探索工程实践之道

京东科技开发者

Mac专用投屏工具:AirServer 7 for Mac 激活版

你的猪会飞吗

AIrserver7 Mac软件下载站 AirServer 7 mac激活版

淘宝商品详情API返回值:深度挖掘其业务价值

代码忍者

pinduoduo API API 性能测试

阿里云可观测 2024 年 9 月产品动态

阿里巴巴云原生

阿里云 云原生 可观测

拍立淘API返回值在商品数据分析中的应用

代码忍者

pinduoduo API API 性能测试

软件测试学习笔记丨二叉树:添加练习

测试人

软件测试

「软件设计哲学」于延保代码改造中的实践

京东科技开发者

登顶!智源BGE首开国产模型Hugging Face月度下载全球第一

智源研究院

天猫商品描述API返回值中的商品参数对比与竞品分析

技术冰糖葫芦

API 接口 API 文档 API 测试 API 性能测试

基于 Nginx 的大型互联网集群架构与实战方案

EquatorCoco

nginx 架构 运维

Python:条件分支 if 语句全讲解

不在线第一只蜗牛

Python

浙江鲲鹏昇腾产业与人才创新论坛成功举办!

Geek_2d6073

打造你的专属语音助手,基于函数计算托管 CosyVoice 语音模型

阿里巴巴云原生

阿里云 云原生 函数计算

数据仓库 Palo 2.0 for Apache Doris 冷热分离原理分析

Baidu AICLOUD

数据仓库 数据仓库服务

一文读懂HyperWorks的耦合求解功能

智造软件

CAE altair hyperworks

云桌面VS传统PC:企业用户该如何取舍

青椒云云电脑

云桌面

如何挑选CDN加速器节点网络?

Ogcloud

CDN 网络加速 CDN加速 企业网络加速 CDN网络加速

什么是iPaaS?iPaaS选型、落地及案例分析

RestCloud

数据集成 应用集成 ipaas

3个步骤轻松集成Push Kit,实现App消息推送

快乐非自愿限量之名

人工智能 深度学习 HarmonyOS

解锁保险新世界-带你走进保险基本法

京东科技开发者

博睿数据Bonree ONE全面适配HarmonyOS NEXT,守护鸿蒙原生应用稳健前行

博睿数据

活动预告|博睿数据将受邀出席GOPS全球运维大会上海站!

博睿数据

繁星·数智思享会第2期:流程挖掘,全知视角驱动业务增长

望繁信科技

流程挖掘 流程资产 流程智能 望繁信科技 数字换转型

在Vue3中如何实现四种全局状态数据的统一管理?

不在线第一只蜗牛

JavaScript vue.js 前端

没有方向盘和踏板,特斯拉发布无人驾驶出租车;字节豆包推出 AI 智能体耳机 Ola Friend丨 RTE 开发者日报

声网

通义灵码 AI 程序员来了!丨阿里云云原生 9 月产品月报

阿里巴巴云原生

阿里云 云原生 通义灵码

内核级流量治理引擎Kmesh八大新特性解读

华为云开发者联盟

服务网格 ebpf Sidecar Kmesh

精准监控,高效运营 —— 商品信息实时分析为商家带来新机遇

技术冰糖葫芦

API 接口 API 文档 API 测试 pinduoduo API API 性能测试

Spring Boot3集成 LiteFlow 实现业务流程编排

江南一点雨

老韩运维知识解析系列02:深入理解网络监控指标与实战应用

Geek_a83400

微服务划分的模式与反模式_服务革新_技术琐话_InfoQ精选文章