当前位置:网站首页>陈珙:微服务,它还那么纯粹吗?
陈珙:微服务,它还那么纯粹吗?
2022-07-01 11:31:00 【DotNet NB】
技术专家
陈珙
轻阅网络科技系统架构师
阿里云开发者社区专家博主
【作者介绍】深耕.Net领域10年,专注微服务架构、分布式系统设计、高并发方案与高效工程化。拥有多年的开发团队管理与系统架构设计经验。广州.Net俱乐部成员,博客园同名作者。
责编 | 韩楠
约 7756 字 | 15 分钟阅读
以下,Enjoy~
01⎪ 温故而知新
不少同行,对于“什么是微服务”,都在各平台发表过相关理解、看法等等。随着这些年的技术发展,不知你发现或者观察到没有,只要涉及到“微服务”这三个字,就已经不再纯粹。几乎不论是什么方向的技术,或多或少会跟微服务扯上关系蹭蹭热度。
当然,也恰恰基于此,使得我这次为什么重提何为微服务,并且单独拿出多个方面结合我的个人见解,想着进一步与大家再深入探讨下。
开头这里,就先抛出我自己的一个观点吧,我并不认为非要把技术弄得多复杂,才显得多牛X。再复杂的物品也是由一件件简单的物品组件形成的,而适当的返璞归真才能看清楚事物的本源。

若想更清晰地了解、理解、搞清楚“微服务是什么”,我认为只需要认真看懂一篇文章就足够了——2014年马丁·福勒个人博客发表的《Microservices》博文(https://martinfowler.com/articles/microservices.html)。
但是,马丁·福勒所著的作品多数是高度总结的,假如你没有亲自实践过,他的作品与思想理解起来相对比较困难,因为他的叙述总体比较抽象。当然,这不影响我自愿重复多次的阅读他的作品——温故而知新。
因此该篇我不会照搬翻译,或是人云亦云,而是会从《Microservices》原文和其他书籍收集回来的资料并结合我的个人见解,来叙述微服务的What、When、Why。

这篇文章没有微服务的How,可能您看完了也不知道应该怎么去实施微服务,但是关系不大,因为我一直坚信,如果你能把某件问题的来龙去脉,清晰无误、通俗易懂地传达给别人,该问题已经解决了70%,那么剩下30%就是寻找解决方法的路上。方法远要比遇到的问题要多得多。
如果您对具体的微服务实践有兴趣,可阅读完该文后移步到《.Net微服务实战》进行扩展阅读(https://www.cnblogs.com/skychen1218/p/16352324.html)。
本篇文章,我将通过选择微服务的原因、微服务的小历史、微服务的特性和我对微服务的个人见解多个角度,分享我对微服务理解的What。你可以总体浏览下大小标题,快速过一遍。抑或是挑自己更为感兴趣的部分,直接跳到那里看。
02⎪ 选择微服务的原因
说到这,我想先问这样一个问题,你选择微服务的原因有哪些呢?可能这问题的回答会百花齐放,无论是哪种原因,促使我们选择微服务终须一个或多个的理由。凡是做任何一件事情,都要有目的性,不可盲目,否则只能是毫无价值的冒进。因此在这我给大家分享下我选择微服务的理由。
︎ 单体应用的优与劣
在早期的开发,单体应用给开发提供了很多的便捷性:
开发简单方便;
项目管理集中;
进程内调试,排查、定位问题更加便捷。
随着团队与业务规模的增加,单体应用的缺陷就会越发的明显,以我个人实践经历,如果希望引入微服务,我认为得满足以下任意3点,则可以考虑选择微服务:
并行开发的代码冲突;
加载、编译、部署项目缓慢;
代码耦合性越来越高;
需要统一数据读写入口;
无法按需扩展。

我早些年遇过10人并行开发共有两三百个项目的解决方案,不论是每次项目加载、编译、部署,其实都非常花时间。只要并行开发就会存在冲突,修改的代码资源越集中,出现合并冲突概率还越大。
在单体应用里,我们会以“库”的方式形成组件,以此来进行单元复用,如果在同一个解决方案里共享复用,使用与修改的自由度会更高。
任何事情都会有利弊的,随着项目的发展,参与的人越多,迭代的频率越高,那么“库”的职责边界就越不清晰,代码耦合也会越发严重。而且因为项目多了,为了方便复用,不同的“应用”引用相同“库”的情况也自然会变多,这样就导致了数据的读写入口扩大,假如数据出了问题:
不好定位原因。
“库”出了问题,相关引用的应用都得重新发布或回滚。

︎ 微服务的优点
微服务的优点有不少,但是我认为核心优点是独立部署与协议统一,而其他的优点都是基于两者之上进行扩展的。因此本小结会着重叙述这两点,剩下的优点我将会在下文结合微服务的特征再进行详细叙述。

微服务其中之一的优点——独立的进程部署,以软件工程的角度出发,从物理层面约束了团队职责,刻意地划分了业务之间的边界,每个开发组(人员)都会清晰了解各自的领域与职责,使得大家优先思考清楚需求的修改点,该由哪个业务组负责。
另外其中一个优点——数据的读写访问统一协议,以技术设计的角度出发,数据的读写操作都被封装成Http API以此隐藏了技术细节,能大幅度降低调用端的技术人员,对非所属业务模块的细节关注,从而把他们注意力转移到所属的业务层面,减少认知负担。
此外,还可以避免非所属业务的技术人员对数据结构做出了不恰当的修改。
总得来说,微服务从工程化的层面解决了不少单体的“老大难”的问题,但是,既然没有“银弹”的存在,那么“新”的技术同样也会带来更多新的挑战,具体的新问题,我将单独拿出来放到新的一篇文章,跟大家详细地分享下,接下来会跟大家分享一下微服务的过去。
03⎪ 微服务的一些小历史
虽然微服务无论是从理论还是实践上解决了不少单体的“老大难”的问题,但是它并不是一门新的技术,其诞生年份得追溯到2005年,而它的设计思想得追溯到Unix的哲学思想,因此,要想了解一样事物的本质,那么就得从它的历史发展说起。

维基百科截图(可点击,放大图片查看)
提到微服务,马丁·福勒这个名字肯定不能忽视,不少人认为马丁·福勒创造的微服务。对于该错误的认知,我认为我有必要应该重新说明下。参考了维基百科(https://en.wikipedia.org/wiki/Microservices#History),我把微服务发展历史整理成了时间线。

从上文的信息,我们可以总结出三个核心关键点:
微服务的起源最早追溯到2005年;
微服务不是由马丁·福勒他本人创造的;
那篇举世闻名2014年写的《Microservices》原文是由詹姆斯·刘易斯和马丁·福勒他们两人共同合作编写的。
虽然说微服务架构并非马丁·福勒创造的,但是称《Microservices》这篇文章是推动微服务崛起的缘由,一点都不为过,而詹姆斯·刘易斯和马丁·福勒两位,对微服务的盛行起到了非常关键的作用。
04⎪ 微服务的特点
上文结合了维基百科分享了微服务的小历史,同时也为微服务、马丁·福勒和《Microservices》原文三者之间的关系,做了个简单叙述,以便大家更加清晰的认识。
︎ 原文的九大特征
既然已经了解了微服务的过去,那么接下来得了解它是什么。马丁·福勒曾经在《NoSQL精粹》写过一句话,他并不喜欢给某件东西下定义。因此在书里,他对于NoSQL总结几大共同特征,而拥有这些特征的存储系统可以称之为NoSQL。
同样,他在《Microservices》原文里,对于微服务架构风格也总结出了微服务具有的9种特性(详细请看下文),而我结合了资料与实践提炼了一下关键字也总结了4个关键特征:

对于原文里的九种特征,还有一段更加精炼的总结。大家看的时候可侧重看我提炼和加粗的关键字,稍后我会结合原文与我的个人总结说一下,以便于帮助你快速抓住分享要点。
原文:
译文:
简而言之,微服务架构风格是一种将单个应用程序拆分为一组小的服务,每个小的服务都在自己的进程中运行并与轻量级机制(通常是HTTP REST API)进行通信。这些服务围绕业务功能构建,并且可以由全自动部署机制独立部署。这些服务几乎没有集中式管理,它可以用不同的编程语言开发,并可以选择不同的数据存储技术。
从上面两段原文,我们可以从中提炼出五小句关键表述:
微服务的起源最早追溯到2005年;由单个应用拆分为一组小的服务(small);
每个服务在独立的进程运行,服务之间使用轻量级的通信机制(lightweight);
服务围绕业务构建,同时服务可以自动化独立部署(independently 、automated);
可以使用不同的编程语言和数据存储(different)。
对以上五个关键词和九大特性,我重新总结了自己的经验并得出以下四个特征:
轻量级(lightweight、small),通信协议和服务应用自身都应该是轻量级的。
自治性(independently),能独立部署运行,且低耦合,服务之间互不影响。
异构性/去中心化(different),可以根据业务特殊性,选择合适的开发语言和存储系统。
自动化(automated),可以由全自动部署机制独立部署。

总地来说,我给微服务的定义是:从软件工程的层面解决了项目臃肿、并行开发冲突、代码耦合度高的问题,并且它具有轻量级、自治性、异构性、自动化四大核心特性的架构风格。接下来,我会根据上述自己总结的关键词和架构设计方法论,跟大家分享一下我对微服务的理解。
05⎪ 业务与团队
我曾经在《十年技术进阶路,让我明白了三件要事》一文提到一句话,我认为可以引用到咱们做架构设计:
做任何事情就如同咱们写代码Function一样,得有输入同时也得有输出,输入与输出之间还得有执行。
业务需求与组织架构是架构设计的两大核心输入,具体原因有以下四点:
设计没有对与错,只有合适与不合适;
业务需求了解度越高,设计合适度则越高;
在能满足需求的前提优先选择简单、合适的方案,避免过度设计;
技术选型应需要考虑自己的团队是否足以支撑。
在《Microservices》原文提到的其中两大特征是与之有关,因此我打算放在一起叙述:
围绕业务能力划分团队(Organized around Business Capabilities)
是产品而不是项目(Products not Projects)
我从原文中的两大特性里分别提炼了两个核心句:
谁构建,谁维护(you build, you run it )
康威定律(Conway's Law)

︎ 业务
早些年我呆过项目制的公司,所有的项目组的成员是通过资源调配临时组建的。职责划分也很清晰,开发部门完成后就QA团队测试,QA完成测试后就交给运维部门负责运营。批次完成后,该项目由谁会继续参与后续批次的开发与维护,一切都是未知的,而眼前的项目如同一次性产物一般。
然而在微服务里,更加希望的是团队的生命周期与产品的生命周期是一致的,谁构建,谁维护(you build, you run it ),这样做的好处有三点:
该团队成员更加熟悉业务,就如前面所说业务是核心输入之一。
对系统、产品有一个持续演进与迭代,这样才会有足够的信息与了解,才足以让系统与产品作出更加合适的优化与设计。
减少跨职责部门沟通的成本,同个业务组所有的成员都会为同一个产品负责,这赋予了他们责任心与共同的目标。
︎ 团队
从以上三点也引出了康威定律(Conway's Law)。
原文:
Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization's communication structure— Melvin E. Conway.
任何组织在涉及一套系统(广义概念上的系统)时,所交付的涉及方案在结构上都与该组织的沟通结构保持一致。
— 梅尔文·康威
用通俗的话描述意思是:其组织架构等同于系统架构,举个例子,该应用是前后端分离的,那么团队得有前端和后端开发,如果该团队与其应用实施了DevOps,还得有运维开发人员等等。
团队会随着产品的演进而变化(扩招,缩编),而原文里提到了两个披萨原则,建议一个团队6-12个人的大小。从我个人的经验来看,一个人的沟通渠道大于5个以上,沟通占据工作上的比例则呈指数级的增加,如果一个团队少于2人,又容易形成单点问题与压力,因此我认为3-5个人是一个比较合理的小组规模。

我曾经跟某企业做技术交流,他们的开发人员是一个人负责多个服务与项目,结合上文叙述的经验角度来看,存在以下三个问题 :
一个人负责多个意味着微服务拆分过细,这个时候思考是否有必须这么细的粒度拆分;
容易造成人员单点维护的问题,容易形成“知识孤岛”“非他不可”的局面;
应该为团队定相同的目标,共同为业务系统负责。
︎ 小结
上文我主要从软件工程的两个角度(业务需求与组织架构),分享了对微服务的理解。
微服务虽然改变了系统、服务之间的架构模式,但也需要足够的组织架构和软件工程与之支撑。技术服务于架构,架构服务于业务,业务服务于商业,这是我架构设计以来坚持的原则,一切的技术与设计,最终用来服务于业务需求,反之,也是商业与业务成就了技术,抛开业务讨论的技术与架构无疑是“耍流氓”的。
06⎪ 抽象与复用
我认为抽象思维,是我们程序员最基本也是最核心的思维方式,抽象思维结合了共性、类比方法,从问题的“质”的角度进行分析与思考,让我们的关注面主要放在对象、动作与关系,使我们减少了因为具象的细节引起的钻牛角尖的情况,恰好架构设计需要我们具有大局观的能力,而大局观的本质正好是抽象思维。
︎ 抽象性
从架构设计思想的抽象角度出发,我认为架构设计的目的主要有三点:确定运作方式、确定职责边界与确定交互方式。
回到微服务,分而治之的本质思想就是"拆",拆是为把耦合性较低的模块是独立成进程进行运作,拆后还得整合把具有关联的服务给组织起来。因此上文的三个设计目的和《Microservices》原文与之对应的三大特性为:
通过服务代替组件(Componentization via Services)
分而治之(Decentralized Governance)
强服务和弱通信(Smart endpoints and dumb pipes)

︎ 复用性
从架构设计思想的抽象角度出发,我认为架构设计的目的主要有三点:确定运作方式、确定职责边界与确定交互方式。
在早些年微服务还没盛行的年代,我们或多或少接触的应用,他们引用公共模块是通过"库"的方式提供的。使用“库“的是为了把具有共性的(抽象性)逻辑模块分离出来,以至于达到物理层面的复用,我们称之抽离出来的单位叫组件(Componen)。
When talking about components we run into the difficult definition of what makes a component. Our definition is that a component is a unit of software that is independently replaceable and upgradeable.
在谈论组件时,我们遇到了如何构成组件的困难定义。我们的定义是, 组件是可独立更换和升级的软件单元。
然而使用这种“库”方式会两个缺点:
如果一个应用引用了10个“库”,任意一个“库”更新了,整个都需要全部更新上去。(一应用、多个库)
如果一个“库”被多个应用引用,如果该“库”出了问题,每个涉及到的应用都更新一遍。(多应用、一个库)

(此图,建议放大查看)
由于以上的问题,我们把这些公共引用的"库",改造为可独立部署的进程进行运作,可独立部署就意味着,只要保证服务之间的通信协议统一性,剩下服务内其他实现,我们就可以自由发挥了——技术异构性。
︎ 技术异构性
我认为在信息系统角度的技术异构性主要分四个层面:硬件、操作系统、开发语言、存储系统。在《Microservices》原文[Decentralized Governance]模块提到,不希望开发人员拥有锤子后,就把任何问题视为钉子,通俗点说,就是希望我们根据不同业务场景、解决方案,去选择对应的技术或开发语言。

因微服务的自治性,给与拥有服务的团队按需部署与选择技术栈的机会,让他们委派决策和控制权,我将从战术与战略两个角度出发跟大家分享我的观点:
从战术层面出发,每个技术人员都会有自己擅长的方向,或许有些人认为,更新换开发语言、更换技术方向不就是换个工具而已这有什么难的?我认为,更换技术方向成本并不在于语言,而是在语言所属的生态与改技术方向的思维。
举个例子,C#可以写做客户端与服务端,但是客户端与服务端的技能生态、设计思维有着本质上的区别。如果是服务端的从C#转Java因语言的特性相似,无疑成本是非常少的,但是我们得熟悉Java语言的生态,例如主流框架、工具、插件等,甚至得踩一遍底层上的坑,例如JVM调优等。
因此,我认为并不存在在某个领域方向很厉害的人,在别领域也同样厉害的说法,经验、知识都是需要时间、实践进行积累的。
再进而回到微服务上,我们并不会刻意去制造技术的异构性,在相同业务领域里,在原有的成熟技术并且能满足业务需求情况下,我建议不要刻意去更换,特别是整个团队。

从战略层面出发,我们关注的是团队与架构,团队与架构都有个共同点,抉择与取舍。在有必要的时候,我们根据业务的发展情况按需扩展。
举个例子:假如现有公司的已有完整的业务模式,需要基于已有的业务继续发展,作为团队负责人的你,对于技术团队采取的策略主要两点:降本与提效。
因此你增加原本团队成本30%基础上成立了一个ToB的低代码团队,在未来半年内出第一个Beta版本,并在一年内投入公司内部生产使用,且预计提高后台系统的300%的开发效率。低代码开发平台,则选择小组组长最熟悉的.Net平台开发,而原有Java团队交接了后台系统的项目,团队人力成本根据业务情况相应的减少10%-20%。

06⎪ Not Only SQL
上文的异构性主要从开发语言与技术选型角度进行叙述,如今这个年代,无论做什么类型的信息系统,基本上离不开存储系统。

︎ NoSQL的特征与类型
20世纪80年代,关系型数据库陆续诞生以来,占据着存储系统的主导地位。随着21世纪的互联网崛起,关系型数据库在高并发与海量数据的场景上,表现的力不从心,而NoSQL的高性能、横向扩展性、多种数据库结构等各种优点,弥补了关系型数据库的不足。在如今的年代混合存储的模式已经是随处可见,NoSQL与关系型数据库的关系,也成为了相辅相成的存在。
马丁·福勒早些年著作的一本书名为《NoSQL精粹》,其中他对NoSQL无法下具体的定义,但是他认为有以下特性的可称之为NoSQL:

马丁·福勒在书中也总结出了共有四种类型的NoSQL,但我个人认为搜素引擎应作为第五种的补充:

︎ 去中心化存储
咱们越是保证了微服务的自治性,去中心化的优势越是更加明显,微服务其中一个特性是非集中式数据管理(Decentralized Data Management),微服务可以根据领域内的业务特点选择合适存储系统,就如上文所提到的技术异构性的存储系统。

关系型数据库在高性能、海量数据与扩展性会有一定的局限性,因此现有的互联网系统不单纯把关系型数据库作为它们唯一的选择,混合型存储才是未来的主流。
简单举两个例子,键值型的Redis作为代表,可以存放会话信息、购物车、缓存等临时性的热数据。搜索引擎以ElasticSearch为例,可以代替关系型数据的Like搜索,也可以作为海量数据业务的Query端的存储。

咱们后端开发的核心关注点,主要以数据读写为主。毫不夸张地说,如果后端开发能把常用的存储系统(关系型与非关系型)了解清楚,在对应的业务场景的选择合适的存储系统,此外对已有的业务,能根据业务特性提出优化方案,相信我们在日常遇到的80%问题都能迎刃而解。
因篇幅有限不再做具体叙述,我这里提供两篇曾经记录存储系统优化的文章,可以供大家参考《后端思维之数据库性能优化方案》和《记一次引入Elasticsearch的系统架构实战》(https://www.cnblogs.com/skychen1218/p/15720522.html)。
07⎪ 总结
到这里,今天这一讲就已接近尾声了。关于前面分享的诸多内容点,为了帮助你快速回顾、梳理、思考,我将全文内容的行文框架、每部分侧重讲解的内容等,整理到图中,这样看的时候,也更直观、明晰,以便于帮助你理解、记忆。

全文思维框架导图
整篇文章的篇幅稍微有点长,最后结合我今天分享的内容,再与你交流下我的一点想法、观点等,此外也算是进一步给大家做了个文章的升级版总结。
从微服务的发展来看,微服务不是马丁·福勒创造的,但是他在推动微服务的发展方面,还是起到了非常重要的作用的。我不是马丁·福勒老爷子的黑粉哈,我还是非常建议大家多看几次老爷子的作品,每次看都会有新的感悟。
虽然我自己很喜欢微服务,包括我最近的时间技术关注点都在微服务上。当时我仍然认为微服务并不能解决一切的技术问题,还是那句老话——没有银弹。微服务给我带来了不少的良性成长,但是我也不会逢人就吹嘘它,因为微服务有它的优缺点,我们得对结合具体问题选择方案,而不是强行地把方案硬塞到某个问题上。
毫不夸张地说,80%的信息系统,甚至可能到90%,如果从客观中立的角度出发、分析,都是不需要用上微服务的。因此,要是您选择了使用单体,正在处理您的项目问题,这并不是一件丢人或者觉得很low的事。

我个人认为微服务的引入,更加侧重的是从软件工程的角度出发考虑的,大家可能听到的什么性能问题啊、高并发啊或者别的问题,选择微服务更多是充分不必要的。
另外再提一嘴,微服务它的本质是无法解决性能问题和高并发的,大家在这里可以停下想想,信息系统的性能问题主要瓶颈在数据库,所以调优方案应该从存储系统的类型、设计、架构方案进行选择;高并发方案,无非是从集群、NoSQL、静态和消息队列这些角度出发进行选择。
只不过微服务实施后,它的自治性特征,可以使得系统在这些高性能和高并发的场景中,拥有更多的扩展余地。
好了,到这里我们就要结束了,非常感谢你耐心的阅读,后面的分享再见。同时期待后续的某几个时段里,我与你能够有更多思想上的交流、碰撞。如果愿意分享,这一讲也欢迎转发给你的朋友,和他一起讨论。还有,对这一讲的内容分享,有疑问或是不同的差异化、多元化想法,可以提出来,留言区里,我们多交流。
点击下方卡片关注DotNet NB
一起交流学习

▲ 点击上方卡片关注DotNet NB,一起交流学习
请在公众号后台


边栏推荐
- Can servers bundled with flask be safely used in production- Is the server bundled with Flask safe to use in production?
- Kafuka learning path (I) Kafuka installation and simple use
- MySQL IN 和 NOT IN () 空列表报错
- Unittest框架中测试用例编写规范以及如何运行测试用例
- Value/string in redis
- redis配置环境变量
- redis中value/hush
- "Target detection" + "visual understanding" to realize the understanding and translation of the input image (with source code)
- 妙啊!MarkBERT
- ES6 Promise用法小结
猜你喜欢
![[Maui] add click events for label, image and other controls](/img/d6/7ac9632681c970ed99c9e4d3934ddc.jpg)
[Maui] add click events for label, image and other controls

Redis configuration environment variables

Harbor webhook从原理到构建

田溯宁投的天润云上市:市值22亿港元 年利润下降75%

Tianrunyun, invested by Tian Suning, was listed: its market value was 2.2 billion Hong Kong, and its first year profit decreased by 75%

Tempest HDMI leak receive 5

S7-1500PLC仿真

Learning summary on June 29, 2022

Numpy的矩阵

软件项目管理 9.2.软件项目配置管理过程
随机推荐
CANN算子:利用迭代器高效实现Tensor数据切割分块处理
分享psd格式怎么预览的方法和psd文件缩略图插件[通俗易懂]
达梦数据冲刺科创板:拟募资24亿 冯裕才曾为华科教授
Can servers bundled with flask be safely used in production- Is the server bundled with Flask safe to use in production?
Packet mode and three streaming modes in SDP protocol
redis中value/String
Value/set in redis
[AI information monthly] 350 + resources! All the information and trends that can't be missed in June are here! < Download attached >
Huawei equipment is configured with large network WLAN basic services
Can I open an account today and buy stocks today? Is it safe to open an account online?
JS date format conversion method
Matrix of numpy
Tempest HDMI leak receive 5
Skip the test cases to be executed in the unittest framework
用于分类任务的数据集划分脚本
VScode快捷键(最全)[通俗易懂]
金鱼哥RHCA回忆录:DO447使用Ansible与API通信--使用Ansible Tower API启动作业
Shangtang entered the lifting period: the core management voluntarily banned and strengthened the company's long-term value confidence
Intel Labs annonce de nouveaux progrès en photonique intégrée
Paxos 入门
