我们从单体架构的优缺点来分析,看看开发大型项目采用单体架构存在哪些问题,而微服务架构又是如何解决这些问题的。
单体架构
单体架构(monolithic structure):将业务的所有功能集中在一个项目中开发,打成一个包部署。之前的hmall项目,所有的业务功能都集中在hmall-service这个模块下,将来部署的时候只需要将其打成一个jar包即可部署,所以之前的项目是单体项目。
单体项目的架构简单,部署成本低。当项目规模较小时,这种模式上手快,部署、运维也都很方便,因此早期很多小型项目都采用这种模式。但随着项目的业务规模越来越大,团队开发人员也不断增加,单体架构就呈现出越来越多的问题:
- 团队协作成本高:试想一下,你们团队数十个人同时协作开发同一个项目,由于所有模块都在一个项目中,不同模块的代码之间物理边界越来越模糊。最终要把功能合并到一个分支,你绝对会陷入到解决冲突的泥潭之中。
- 系统发布效率低:任何模块变更都需要发布整个系统,而系统发布过程中需要多个模块之间制约较多,需要对比各种文件,任何一处出现问题都会导致发布失败,往往一次发布需要数十分钟甚至数小时。
- 系统可用性差:单体架构各个功能模块是作为一个服务部署,相互之间会互相影响,一些热点功能会耗尽系统资源,导致其它服务低可用。
在上述问题中,前两点相信大家在实战过程中应该深有体会。对于第三点系统可用性问题,很多同学可能感触不深。接下来我们就通过黑马商城这个项目,给大家做一个简单演示。
首先,我们修改hm-service
模块下的com.hmall.controller.HelloController
中的hello
方法,模拟方法执行时的耗时:
接下来,启动项目,目前有两个接口是无需登录即可访问的:
http://192.168.202.128:8080/hi
http://192.168.202.128:8080/search/list?pageNo=1&pageSize=5
经过测试,目前/search/list
是比较正常的,访问耗时在200毫秒左右。
接下来,我们假设/hi
,这个接口是一个并发较高的热点接口,我们通过Jemeter
来模拟500个用户不停访问。下面资料中已经提供了Jemeter
的测试脚本:
通过网盘分享的文件:jemeter
链接: https://pan.baidu.com/s/1phuOtb3RrLw67maj9-S0kg?pwd=9a8k 提取码: 9a8k
--来自百度网盘超级会员v5的分享
下载Jemeter,并配置环境变量:
jemeter依赖于jdk,需要有jdk才可以。Jemeter安装包在上面资料中已经存在,解压。
首先配置JEMETER_HOME
D:\develop\apache-jmeter-5.6.3
然后再配置CLASSPATH
将ApacheJMeter_core.jar
文件和jorphan.jar
文件的路径配置到CLASSPATH里
%JEMETER_HOME%\lib\ext\ApacheJMeter_core.jar;%JEMETER_HOME%\lib\jorphan.jar
最后将bin目录添加到Path里
使用cmd命令,启动jmeter
导入JMeter
并测试:
这个脚本会开启500个线程并发请求http://localhost/hi
这个接口。由于该接口存在执行耗时(500毫秒),这就服务端导致每秒能处理的请求数量有限,最终会有越来越多请求积压,直至Tomcat资源耗尽。这样,其它本来正常的接口(例如/search/list
)也都会被拖慢,甚至因超时而无法访问了。
启动测试脚本,然后在浏览器访问http://192.168.202.128:8080/search/list
这个接口,会发现响应速度非常慢:
如果进一步提高/hi
这个接口的并发,最终会发现/search/list
接口的请求响应速度会越来越慢。这就是某一个接口并发太高,把Tomcat资源占完了,这样其他的进程访问的时候就很难进来了。
可见,单体架构的可用性是比较差的,功能之间相互影响比较大。此时如果我们对系统做水平扩展,增加更多机器,资源还是会被这样的热点接口占用,从而影响到其它接口,并不能从根本上解决问题。这也就是单体架构的扩展性差的一个原因。而要想解决这些问题,就需要使用微服务架构了。
微服务
微服务架构,首先是服务化,就是将单体架构中的功能模块拆分成多个独立的项目。同时要满足下面的一些特点:
- 粒度小:每个功能模块拆分出去的要小一点,按照业务来拆分,拆出去的每个项目都要负责一块完整的功能,单一职责。
- 团队自治:每个微服务项目都由单独的团队独立的开发和维护,团队人员规模不超过10人(2张披萨能喂饱)。
- 服务自治:每个微服务都独立打包部署,访问自己独立的数据库。并且要做好服务隔离,避免对其它服务产生影响
例如,黑马商城项目,我们就可以把商品、用户、购物车、交易等模块拆分,交给不同的团队去开发,并独立部署:
那么,单体架构存在的问题有没有解决呢?
- 团队协作成本高?
- 由于服务拆分,每个服务代码量大大减少,参与开发的后台人员在1~3名,协作成本大大降低
- 系统发布效率低?
- 每个服务都是独立部署,当有某个服务有代码变更时,只需要打包部署该服务即可
- 系统可用性差?
- 每个服务独立部署,并且做好服务隔离,使用自己的服务器资源,不会影响到其它服务。
综上所述,微服务架构解决了单体架构存在的问题,特别适合大型互联网项目的开发,因此被各大互联网公司普遍采用。大家以前可能听说过分布式架构,分布式就是服务拆分的过程 ,其实微服务架构正是分布式架构的一种最佳实践的方案。
当然,微服务架构虽然能解决单体架构的各种问题,但在拆分的过程中,还会面临很多其它问题。比如:
- 如果出现跨服务的业务该如何处理?
- 页面请求到底该访问哪个服务?
- 如何实现各个服务之间的服务隔离?
这些问题,我们在后续的学习中会给大家逐一解答。
SpringCloud
微服务拆分以后碰到的各种问题都有对应的解决方案和微服务组件,而SpringCloud框架可以说是目前Java领域最全面的微服务组件的集合了。
而且SpringCloud依托于SpringBoot的自动装配能力,大大降低了其项目搭建、组件使用的成本。对于没有自研微服务组件能力的中小型企业,使用SpringCloud全家桶来实现微服务开发可以说是最合适的选择了!
https://spring.io/projects/spring-cloud#overview
目前SpringCloud最新版本为2022.0.x
版本,对应的SpringBoot版本为3.x
版本,但它们全部依赖于JDK17,目前在企业中使用相对较少。
SpringCloud版本 | SpringBoot版本 |
---|---|
2022.0.x aka Kilburn | 3.0.x (jdk17) |
2021.0.x aka Jubilee | 2.6.x, 2.7.x (Starting with 2021.0.3) |
2020.0.x aka Ilford | 2.4.x, 2.5.x (Starting with 2020.0.3) |
Hoxton | 2.2.x, 2.3.x (Starting with SR5) |
Greenwich | 2.1.x |
Finchley | 2.0.x |
Edgware | 1.5.x |
Dalston | 1.5.x |
因此,我们推荐使用次新版本:Spring Cloud 2021.0.x
以及Spring Boot 2.7.x
版本。
另外,Alibaba
的微服务产品SpringCloudAlibaba
目前也成为了SpringCloud
组件中的一员,我们课堂中也会使用其中的部分组件。
在我们的父工程hmall中已经配置了SpringCloud
以及SpringCloudAlibaba
的依赖:
对应的版本:
spring-cloud-dependencies的pom文件里面定义了各种各样的组件,也就是spring-cloud内部所有的组件在里面基本上都有对应的版本。因此,在引入spring cloud dependencies之后,在开发的过程中就不需要自己指定组件对应的版本,将来用到哪个组件直接将组件引入过来不需要单独指定版本号。