有不少小伙伴希望松哥能整一个微服务的实战项目,微服务这块技术点其实松哥是讲过很多了,图文版的教程视频版的教程都有,不过确实缺乏一个项目,所以我在想等 TienChin 项目搞完之后,和小伙伴们也来一起搞一个微服务的项目。
今天我想从架构的角度来和小伙伴们聊一聊微服务。不聊具体的技术点,就单纯来看看一个微服务项目该怎么设计。
1. 单体版 TienChin
松哥目前在录的 TienChin 项目就是一个前后端分离的单体项目,采用了 Spring Boot + Vue3。那么单体版的 TienChin 具有什么样的特征呢?我从优点和缺点两个方面来和大家分析。
先来看一张简单的架构图:
可以看到,虽然是单体项目,但是为了开发方便,项目也细分为许多不同的模块,项目中的适配器可以分为两大类:
入站适配器:就是外部系统来调用我们的系统,REST API 和 Vue 网页都算是入站适配器,外部系统通过这两个接口来调用我们的系统。
出站适配器:这个主要是我们系统内部调用外部系统的方式,例如我们的项目中需要用到 MySQL、Redis等,那么就通过出站适配器来实现。
1.1 优点
开发简单:随便一个 IDE,撸起袖子就可以开写了。
测试简单:项目启动之后,直接利用 POSTMAN 等工具就可以测试项目接口了。
部署简单:项目开发完成之后,打包成一个 jar 或者一个 war,直接部署就行了。
横向扩展简单:当项目并发能力不足的时候,可以方便的结合 Nginx 等负载均衡工具进行横向扩展。
可以看到,单体项目的优势整体上来说还是非常明显的。
1.2 缺点
然而缺点也是非常明显的。
项目越来越复杂
首先就是项目不可能一直这么简单,我们这个项目中还是细分了很多不同的模块。随着时间的推移,这些模块会变得越来愈复杂。修改每一个 BUG 都要小心翼翼,牵一发而动全身。并且随着项目组中人员的离职/入职,新接手的人会让这个项目更加复杂,每一次 BUG 的修复或者新功能的添加,都会让这个项目变得更加“不可捉摸”。
- 开发进度越来越不可控
由于系统越来越复杂,我们不得不增派人手参与到这个项目的开发中,以期推进项目进度。这么多人的协调又是一个问题。并且,随着项目越来越大,每一次编译运行都得数分钟、十几分钟甚至更久,这也会严重拖慢我们的项目进度。
发版周期过长
单体项目发版很多小伙伴可能都刻骨铭心,发版当天如临大敌,所有人都加班,等项目上线运行都没问题,各项数据都 OK,此时可能已经凌晨三四点了,所有人拖着疲惫的身体下班。正是由于每一次发版都是一个大事,所以一般单体项目不太会频繁发版(我说的频繁是指如一天一版这种),发版周期普遍比较长。
难以扩展
当系统不同模块对资源的需求不同的时候,我们想做针对性的硬件扩展也并不方便。
举个简单例子,有一个模块需要进行大量的运算,我们希望能为之提供更好的 CPU;有一个模块需要更大的内存,我们需要扩展更大的内存。
然而由于所有的模块都打包在一起,我们只能针对当前服务器做各种硬件升级,无法针对某一个模块做专门的硬件升级。
过期的技术栈不易更新
我相信很多小伙伴见到的单体项目还有一个特点就是技术栈普遍比较老旧。这也是因为单体项目时间久了之后,积重难返,想要对基础框架做版本升级往往牵一发而动全身,更别提从传统的 SSM 切换到 Spring Boot 上这种超级繁琐的工作了。因此大部分的单体项目,在立项的那一刻选用了什么技术栈、选用了技术的哪个版本,基本上这个项目未来都是这个版本了。
从上面的介绍中小伙伴们可以看到,单体项目优点很明显,然而缺点也是非常明显的。而这些缺点,都可以通过微服务来解决。
2. 微服务版 TienChin
如果 TienChin 项目是微服务版呢?我们来看一张简单的架构图。
简单画了张图,我来解释下:
首先我们基本上是按照业务来划分服务的。每一个服务都有自己独立的数据库,自己操作自己的库。
假设在线索管理中,需要调用商机管理,那不能直接操作商机的数据库,必须去调用商机管理服务中提供的 REST API,通过这个 REST API 来操作库。
所有的服务有一个统一的入口 Gateway,如果前端是手机 App 或者小程序之类的,通过 Gateway 来访问到系统。
有一个后台管理的 Web UI 项目,提供相应的网页操作。
大致上就是这个样子。
那么这个微服务版的 TienChin 跟前面的单体版 TienChin 相比优势体现在哪里呢?
容易维护
首先第一点就是,项目拆分为微服务之后,每个服务相对来说都比较小,项目的维护相对来说也会比较容易。一个比较小的项目,在 IDE 中启动也会比较快。可以有一个很小的团队来负责项目的维护。
服务可以自由扩展
以上图为例,如果某日搞促销活动,线索管理这个服务的并发量比较大,我们可以非常方便的为线索管理模块做横向扩展,如下图这样:
任何一个服务,如果有需求,都可以非常方便的进行扩展,并且可以根据服务的特点来选择合适的硬件,例如这个服务耗内存,那就加大内存;另一个服务耗 CPU,那就选择一个性能到位的 CPU 等等。
解耦后更强的容错性
通过服务降级、熔断等微服务组件的使用,我们可以实现各个微服务具备更强的容错性。一个服务出故障,并不会影响其他的服务。例如合同管理里边发生了内存泄漏,这个并不会影响到商机管理服务。
更容易采用新技术
之前我们在谈到单体项目的弊端的时候,提到了单体项目的技术栈更新非常不易。现在我们切换成微服务了,新技术栈的切换其实就变得非常容易了。每一个微服务都可以根据当前项目的情况,选择是否采用最新的技术栈,而且一个微服务在切换最新技术栈的过程中,如果不幸发生了问题了,也不会影响到其他的微服务,只会影响到当前的服务。由于各个微服务之间基本上都是通过 REST API 进行交互的,所以,退一万步,你甚至可以使用不同的开发语言来开发不同的微服务。
更友好的 CI/CD
CI/CD 是 DevOps 的一部分,但是在前面的单体项目中,当项目比较大的时候,想做到持续交付/持续部署已经越来越难了,而微服务让一个超大规模的项目可以非常方便的实现 CI/CD。
现在,我们的每一个服务都有自己独立的团队、独立的代码仓库、独立的自动化部署流水线,且互不相扰,如下图这样:
现在,每一个服务都可以独立的实现服务的上线和部署,结合 DevOps 可以做到非常轻松的发版,不需要再像以前单体应用发版的时候,如临大敌一样。
这样划分之后,工程师也可以将自己的精力放在业务开发商,提供更多有价值的功能,而不是像一个救火队员一样,每天忙着四处灭火。
好啦,通过这样一篇简单的文章和图片,希望大家对微服务有一个基本的认知,当然,微服务也不是“银弹”,微服务架构也存在问题,这个咱们后面有空了松哥再继续和小伙伴们分享。