微服务并不能解决你的烂代码问题

架构师修行之路

共 3709字,需浏览 8分钟

 ·

2021-08-20 14:58

点击上方蓝字关注我们

微服务并不能解决你的烂代码问题

很久以来,软件的交付质量一直是一个大家比较关心的问题,而程序员和架构师也一直在极力寻找一种更好的方式来构建应用系统。随着互联网爆炸式的增长,对于系统的交付速度和质量的要求也日渐提高,这不仅对程序员写的程序,而且对架构师对整个系统的架构能力提出了更高的要求。

如果你学过领域驱动设计,你会知道系统的构建应该建立在业务模型之上,而不是围绕着数据库的表,视图,存储过程。如果你学过系统设计的六边形理论,你同样也会知道提炼业务核心模型才是构建一个具有可扩展性系统的重心所在。如果你了解过CI/CD,从客户的满意度来说,持续交付要比瀑布模型交付好太多。

image
image
image

再加上非功能性的一些需求,最典型的:系统的高可用,高扩展性,高性能。这一系列要求对于传统的开发模式根本不可能满足。伴随着容器技术,基础设施自动化,大型集群的流行,微服务也慢慢的浮出水面。它并不是被发明出来的,而是随着软件系统的不断发展衍生出来的。

最重要的是很多公司在采用了微服务的架构之后确实明显改善了软件系统的交付速度和质量,并且可以有更多的机会去尝试新的技术,比如现在流行的容器技术,云原生,Serverless等。在团队与团队之间,职责更加清晰明显,而且不同技术栈的团队也可以很融洽的进行合作。

当然,我比较排斥那种为了效仿而进行的技术改革。每个公司都有自己的技术沉淀以及债务,不要妄图利用一种完美的技术来填平所有的焦油坑。

微服务

到目前为止,网络上关于微服务的定义有很多版本,无论什么样的文字定义都始终围绕着以下核心:

微服务是一组小而自治并且能协同工作的系统服务。它不仅仅是代码级别的重用,更重要的是业务级别的重用和自治。

这让我不禁想到了“中台”的定义,中台其中一个很明显的目标是要达到公司业务级别的重用,进而反馈给业务一些结果来达到闭环效果。

image
微服务一定要足够小吗?

每一个系统,在诞生的时候其实都很小,随着产品的不断发展,才会赋予这个系统更多的职能,但是,这个系统最主要的特点仍然是:一个单体应用

什么叫单体应用?说白了,所有的代码都在一个工程中,对外输出的也只有一个工程。每次修改任何一个功能,哪怕是修改一个字符,都需要重新发布。

随着时间的推移,当这个单体越来越大的时候,你会发现大量的重复性代码,大量的重复性功能,甚至会存在大量的重复性SQL语句。这些还只是表面现象,如果想要修改一个功能,居然会意想不到的影响很多地方,随着人员的离职等情况,这些代码没有人会熟悉,慢慢的传说中的“屎山”出现了。

image

如果有一个技术且职责比较上心的技术经理或者总监,一些单体应用至少还会根据不同的模块进行抽象,用接口的方式来达到代码内的职责分离和高内聚。这里多说一句:高内聚,松耦合在设计任何系统的时候都非常重要,尤其在大的单体系统应用中。

把因为相同原因而变化的模块(代码)划分到一起,而把不同原因而变化的模块(代码)分离出来

高内聚松耦合可以说在微服务中体现的淋漓尽致,因为微服务就是按照业务的不同模块来进行划分的,微服务之间拥有明确的业务边界,某个功能属于哪个微服务,应该写在哪个微服务里,一目了然。

至于微服务的划分粒度,说实话,业界并没有一个明确的标准。但是服务之间的边界是明确的,假如说:一个微服务内还存在多个小模块,这些小模块是否也应该划分为更小的微服务呢?这本质上还是微服务粒度划分的问题,也是一个没有明确答案的问题,不过却可以依据一下几个准则去进行微服务的规划:

  • 模块的大小。如果一个模块可以在两周之内进行重写,那这个模块完全可以独立成微服务。
  • 模块是否存在独立的变化。如果一个模块会频繁变化,可以考虑独立成一个单独的微服务。
  • 模块是否具有比较高的性能需求。如果一个模块在性能这个指标上有比较高的要求,为了应对这种要求可以划分为独立的微服务。
  • 虽然每个人对小都没有明确的概念,但是对“大”却有着明确的敏感性。当你感觉一个系统“大”的时候,就可以考虑进行拆分了

警告:系统进行微服务的拆分,并非是越小越好,更多的时候在拆分的时候要根据团队,运维能力等进行综合考虑,在总量不变的情况下,小意味着数量多,数量多意味着必须要投入更多的人力物力去管理运维,并且也会引入分布式下的很多问题。这个之后咱们具体详聊.....

微服务优势明显吗?

到目前为止,全网都在吹嘘进行微服务的划分,但是在脱离具体业务场景的条件下,大力倡导拆分微服务,这很明显就是在教人耍流氓而不负责任。我某天看到一篇文章返璞归真的要回归单体应用,我看完之后默默的点了个赞,从文章中具体的业务来说,确实采用单体应用比微服务更合适,因为他们的业务边界很模糊,可以说没有业务边界,一味的进行微服务划分,带来的是一系列的分布式问题,对于公司而言反而没有益处。

说到微服务的优势,一般都是对比单体服务来说的,单体应用有哪些缺点呢?

  • 开发效率低:所有的开发在一个项目改代码,递交代码相互等待,代码冲突不断
  • 代码维护难:代码功能耦合在一起,新人不知道何从下手
  • 部署不灵活:构建时间长,任何小修改必须重新构建整个项目,这个过程往往很长
  • 稳定性不高:一个微不足道的小问题,可以导致整个应用挂掉
  • 扩展性不够:无法满足高并发情况下的业务需求

这些你都可以用百度搜到,这里不再详细展开了。微服务的优势明显吗?我想说,对于很多大型系统确实很奏效,但是对于一些中小型系统,那就不一定了。

就像很多架构师吹嘘的充血模型一样,一味的贬低贫血模型一无是处,无形中总是在拉低自己的格局。

高扩展性

当系统处于单体系统的时候,如果某一个模块遇到性能问题或者想要保证高可用特性,只能将整个系统进行多份部署来达到目的,哪怕是只有一个小小的部分存在性能问题。如果把这一部分进行了微服务的拆分,那么就可以只针对这个微服务进行扩展了,无论是性能还是高可用的要求,都可以单独进行,而不必影响其他模块,而且公司对于成本问题上要低很多。

举一个简单例子:假如有一个电商系统,包含了商品,订单,支付等模块,对于性能而言,用户浏览商品量要比下订单量大很多,很显然,商品模块对于性能有着更高的要求,这个时候就可以考虑把商品这个模块独立出来,以便提供横向扩展的高性能能力。

弹性

在传统的单体系统中,当服务不可用的时候,就意味着所有的模块都不可用,虽然也可以通过部署多份大单体的方式来降低这个概率,但是这种方式始终是种诟病。在微服务架构中,如果一个服务不可用,并不会影响全部的服务,当然如果做好了微服务的降级,限流等工作,将会把影响降低到最低。

部署简单

在大单体时代,哪怕是修改了一行代码也需要重新编译整个项目来进行重新部署,这种部署方式其实隐含的风险非常大,所以很多大单体的运维人员都不会频繁进行项目的部署,而且部署的时候很多时候要准备好通宵(因为风险大),尤其是那种多个迭代的大部署行为。在微服务的架构下,每个微服务都是独立部署的,这样就可以针对迭代进行更快的上线操作,而不影响其他服务,而且就算是线上出问题,回滚操作也非常快。能够快速的迭代新功能意味着用户可以快速的尝试新功能,这在我们交付高质量的软件是非常有利的。

技术自由

由于每个微服务之间交互都采用RPC或者REST进行交互,而这些交互方式又有着严格的规范,所以每个微服务采用什么技术栈是相对自由的,不同团队之间技术的差异性在微服务架构下不复存在,而且每个团队都可以尝试一些新技术,最重要的是每个微服务都可以根据自身的业务特点来进行合适的技术选型,比如:当一个典型的文档存储微服务,我们可以选择采用mongoDB来做存储;当一个搜索型微服务,我们可以采用ES来做存储。

image
程序员的福音

在大单体的时代,时常会发生“我的代码被哪个孙子改了”的情况,由于大家都在一个大的代码库进行工作,还会偶尔发生代码互相覆盖的情况(我想很多人都发生过这种情况)。而在微服务的架构下,每个划分出来的微服务都有自己的独立代码仓库,最重要的一点这个代码仓库只有一个团队在使用,至于团队内的沟通要比团队之间沟通畅快的多,所以代码管理这部分几乎不会出现什么问题。

同一个业务的功能,只需要开发一遍,至于使用端是网页,还是桌面,还是小程序或者app,都可以重用一套接口,真正的实现了业务上的重用。这才是程序员想要的结果啊!!!!

而且对于某个微服务的重构工作会非常顺利,因为每个微服务的代码量不会很大,而且业务也很清晰,这在大单体时代是不存在的。

总结

就像“人月神话”中描述的一样,微服务也并非银弹。如果一个架构师盲目的进行微服务的拆分会面临着分布式系统的一系列的问题,比如:网络的不可靠性带来的问题,分布式事务带来的一致性问题,分布式监控的问题,还有最重要的CAP抉择问题等。所以:

微服务有时候可能并不适合你,谁用谁知道!!!



No END

浏览 13
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报