发布于 

微服务:我们需要从单体转到微服务吗?

微服务或许你没有真正实践过,但一定听说过,虽然已经到了 2022 年,这个词依然很热,可以通过搜索 google 指数看得到。

起源

“微服务”一词源于 2011 年 5 月在威尼斯附近的一次软件架构师研讨会上进行的架构风格的讨论。2012 年 5 月 讨论小组决定将这种架构风格命名为“微服务”。 Fred George 同年在一次技术大会上进行自己的微服务实践分享,并说微服务是一种细粒度的 SOA ,但最终将其发扬光大的是 Martin Fowler 2014 年写的博文《 Microservices 》,原文链接如下:

https://martinfowler.com/articles/microservices.html

自此以后,微服务就家喻户晓了,Microservices 的 Google 指数也是在 2014 年后就一路飙升。

和微服务相对应的是单体架构,先来看看单体架构是怎样的。

单体架构

大多数人做软件开发应该都是从单体架构开始的,以 .NET 程序员来说,从最早的 WebForm、到后来的 MVC、再到现在的前后端分离,后端使用 .NET 的 WebAPI ,都是整个项目的代码放到一个解决方案中,发布要么直接整个目录进行替换,或者更新有变更的 dll 文件。

包括到现在,这种单体架构的模该还占着很大的比重,凡是存在,必有道理,单体架构有着他的可取之处:

  • 开发方便,.NET 程序员只需只需使用宇宙最强 IDE VS 就可以;
  • 调试方便,在开发阶段,所有的项目都在一个解决方案下,项目之间是可以直接引用,断点可以到达你想要的任何地方;
  • 运行方便,编码完成,只需一个 F5 搞定;
  • 部署方便,无论是之前部署 IIS ,还是现在的容器部署,都只涉及到一个发布目录。

不过,随着产品的功能越来越复杂,代码也会变得越来越复杂,团队的人数也会越来越多,这时单体架构就会带来一些问题:

  • 因为代码库非常的臃肿,从编译、构建、运行到测试这个时间会越来越长;
  • 技术栈几乎是受限的,比如一个 .NET 的工程,基本就是 C# 来开发了,不太可能混杂其他的语言;
  • 不方便横向扩展,只能整套程序进行扩,满足所有模块的需求,对资源的利用率非常差;
  • 不够敏捷,团队成员越来越多多时,都在同一个代码上进行修改、提交、合并,容易引发冲突和其他问题;
  • 一个很小的改动点,容易引发全身问题,导致系统崩溃,因为影响点多,测试成本也会很高;
  • 缺乏可靠性,我们就碰到过因为一个序列化的问题导致 CPU 占用很高,结果整个系统瘫痪了。

微服务架构

上面提到的单体架构存在的问题,采用微服务架构可以很好地解决。微服务的核心是为了解耦,构建成一个松耦合的分布式系统。

一个庞大的单体系统拆分成若干个小的服务,每个服务可以由一个小的团队来维护,团队会更加敏捷,构建发布的时间更短,代码也容易维护。

不同的微服务团队可以采用不同的技术栈,比如工作流引擎使用 .NET ,规则引擎可以使用 Java ,一些全新的模块更容易采用新的技术,人员流动和补充上也更加灵活。

每个服务通常采用独立的数据库,代码或者数据库层面的问题不会导致整个系统的崩溃。

扩展方便,这个很重要,如果监控发现流程引擎的压力很大,可以只针对这个服务进行横向扩展,服务器资源可以得到更好的利用。

上面说的都是好处,但没有任何一种技术是银弹,微服务解决问题的同时,也会带来更多的问题。

1、开发调试变得困难了,需要通过日志的方式或者借助一些远程调试工具;

2、单体架构中,模块之间的调用都是进程内,添加类库的引用后,就是本地方法的调用,微服务各自独立部署,就会涉及到进程间的通信;

3、线上问题往往需要多个服务团队一起来协作解决,会存在互相甩锅的问题;

4、在分布式系统中,事务、数据一致性、联合查询等相比较单体更加复杂;

5、持续集成、部署、运维的复杂度也显著提升;

6、随着服务越来越多,客户端怎样去找这些服务呢?

7、进程内的访问不存在网络的问题,拆分后的服务可能在同个机器的不同进程,更多的时候是不同机器的不同进程,网络问题导致服务不稳定怎么办?

为了解决这些问题,各种中间件和框架就应运而生,又会带来更多的学习成本。

在 .NET 技术栈中,会用到下面这些中间件:

  • 服务注册与发现:Consul
  • 网关:Ocelot
  • 熔断降级:Polly
  • 服务链路追踪:SkyWalking 或 Twitter 的 Zipkin
  • 配置中心:Apllo
  • 鉴权中心:IdentityServer4

在 Java 中也有 Spring Cloud 和 Spring Cloud Alibaba 这种全家桶套件可以使用。

要不要转微服务呢?

从单体到微服务是一个权衡和取舍的问题,切记不要跟风。以我的经验来看,可以分为两类:

1、做企业级系统;

2、做互联网系统。

做企业级应用大多都是项目交付型的,客户关系维系的好,后面可以做二期、三期,当然也有一锤子买卖的。这其中一个关键点是要快,单从快速来看,采用单体架构,开发、调试、部署都是最快的。

从客户角度来说,只要能满足业务,是单体还是微服务其实不太关心。

做互联网应用,也就是我们常说的 SaaS,也分为两种情况:

1、将现有的私有化部署的系统(单体架构)改造成支持 SaaS 的模式。

这种我也不建议一上来就大刀阔斧地进行微服务改造,可以在代码的结构上做一些调整,比如按照领域去拆分目录,不同领域之间的调用可以再进行一层抽象,目的是为了未来向微服务架构转化。

当团队的技术栈变得丰富了,比如原先只有 .NET ,现在有些模块采用的是 Java ,这时已然是朝着微服务架构发展了,只是粒度比较大而已,相应的一些中间件也需要引入,比如服务网关、服务发现、服务间通信等。

2、从零开始做一个 SaaS 系统。

互联网系统和企业级系统有很大的差别,如果说企业级系统更多关注功能性需求,那么互联网系统除了功能性需求,还需要关注非功能性需求,比如:横向扩展、限流降级、日志追踪、预警、灰度发布等。

即便因为时间关系,一开始是单体架构,我觉得也应该是微服务架构的单体,随着持续迭代和发展,根据实际情况逐步进行拆分。

如果时间上比较充裕,可以一开始就按照微服务架构进行分离,但粒度不要太小。

总结

1、解决常说的的三高问题(高并发、高性能、高可用),一个核心的思路就是拆,分而治之,所以说微服务肯定是能解决掉我们的很多问题,也是发展方向;

2、实践微服务需要根据当前的实际情况,如果单体运行的很好,也没什么问题,也不要为了炫技进行微服务改造;

3、如果决定要实践微服务,先做好单体架构的设计,让代码遵循面向对象的设计原则,否则即便形式上变成了微服务,也不能尝到微服务的甜头。