之前我们学习的项目一是单体项目,可以满足小型项目或传统项目的开发。而在互联网时代,越来越多的一线互联网公司都在使用微服务技术。
从谷歌搜索指数来看,国内从自2016年底开始,微服务热度突然暴涨:
那么:
- 到底什么是微服务?
- 企业该不该引入微服务?
- 微服务技术该如何在企业落地?
接下来几天,我们就一起来揭开它的神秘面纱。
计划是这样的,课前资料中给大家准备了一个单体的电商小项目:黑马商城,我们会基于这个单体项目来演示从单体架构到微服务架构的演变过程、分析其中存在的问题,以及微服务技术是如何解决这些问题的。
你会发现每一个微服务技术都是在解决服务化过程中产生的问题,你对于每一个微服务技术具体的应用场景和使用方式都会有更深层次的理解。
今天作为课程的第一天,我们要完成下面的内容:
- 知道单体架构的特点
- 知道微服务架构的特点
- 学会拆分微服务
- 会使用Nacos实现服务治理
- 会使用OpenFeign实现远程调用
0.导入黑马商城项目
在课前资料中给大家提供了黑马商城项目的资料,我们需要先导入这个单体项目。不过需要注意的是,本篇及后续的微服务学习都是基于Centos7系统下的Docker部署,因此你必须做好一些准备:
- Centos7的环境及一个好用的SSH客户端
- 安装好Docker
- 会使用Docker
如果你没有这样的Linux环境,或者不是Centos7的话,那么这里有一篇参考文档:
建议按照上面的文档来搭建虚拟机环境,使用其它版本会出现一些环境问题,比较痛苦。
如果已经有Linux环境,但是没有安装Docker的话,那么这里还有一篇参考文档:
如果不会使用Docker的话可以参考黑马的微服务前置Docker课程,B站地址如下:
https://www.bilibili.com/video/BV1HP4118797/?share_source=copy_web&vd_source=3362e6914fb759983690e6e0f1072453
注意:
如果是学习过上面Docker课程的同学,虚拟机中已经有了黑马商城项目及MySQL数据库了,不过为了跟其他同学保持一致,可以先将整个项目移除。使用下面的命令:
cd /root
docker compose down
0.1.安装MySQL
在课前资料提供好了MySQL的一个目录:
其中有MySQL的配置文件和初始化脚本:
我们将其复制到虚拟机的/root
目录。如果/root
下已经存在mysql
目录则删除旧的,如果不存在则直接复制本地的:
然后创建一个通用网络:
docker network create hm-net
使用下面的命令来安装MySQL:
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123 \
-v /root/mysql/data:/var/lib/mysql \
-v /root/mysql/conf:/etc/mysql/conf.d \
-v /root/mysql/init:/docker-entrypoint-initdb.d \
--network hm-net\
mysql
此时,通过命令查看mysql容器:
docker ps
如图:
发现mysql容器正常运行。
注:图片中的dps命令是我设置的别名,等同于docker ps --format,可以简化命令格式。你可以参考黑马的day02-Docker 的2.1.3小节来配置。
此时,如果我们使用MySQL的客户端工具连接MySQL,应该能发现已经创建了黑马商城所需要的表:
0.2.后端
然后是Java代码,在课前资料提供了一个hmall目录:
将其复制到你的工作空间,然后利用Idea打开。
项目结构如下:
按下ALT
+ 8
键打开services窗口,新增一个启动项:
在弹出窗口中鼠标向下滚动,找到Spring Boot
:
点击后应该会在services中出现hmall的启动项:
点击对应按钮,即可实现运行或DEBUG运行。
不过别着急!!
我们还需要对这个启动项做简单配置,在HMallApplication
上点击鼠标右键,会弹出窗口,然后选择Edit Configuration
:
在弹出窗口中配置SpringBoot的启动环境为local:
点击OK配置完成。接下来就可以运行了!
启动完成后,试试看访问下 http://localhost:8080/hi 吧!
0.3.前端
在课前资料中还提供了一个hmall-nginx的目录:
其中就是一个nginx程序以及我们的前端代码,直接在windows下将其复制到一个非中文、不包含特殊字符的目录下。然后进入hmall-nginx后,利用cmd启动即可:
# 启动nginx
start nginx.exe
# 停止
nginx.exe -s stop
# 重新加载配置
nginx.exe -s reload
# 重启
nginx.exe -s restart
特别注意:
nginx.exe 不要双击启动,而是打开cmd窗口,通过命令行启动。停止的时候也一样要是用命令停止。如果启动失败不要重复启动,而是查看logs目录中的error.log日志,查看是否是端口冲突。如果是端口冲突则自行修改端口解决。
启动成功后,访问http://localhost:18080,应该能看到我们的门户页面:
1.认识微服务
这一章我们从单体架构的优缺点来分析,看看开发大型项目采用单体架构存在哪些问题,而微服务架构又是如何解决这些问题的。
1.1.单体架构
单体架构(monolithic structure):顾名思义,整个项目中所有功能模块都在一个工程中开发;项目部署时需要对所有模块一起编译、打包;项目的架构设计、开发模式都非常简单。
当项目规模较小时,这种模式上手快,部署、运维也都很方便,因此早期很多小型项目都采用这种模式。
但随着项目的业务规模越来越大,团队开发人员也不断增加,单体架构就呈现出越来越多的问题:
- 团队协作成本高:试想一下,你们团队数十个人同时协作开发同一个项目,由于所有模块都在一个项目中,不同模块的代码之间物理边界越来越模糊。最终要把功能合并到一个分支,你绝对会陷入到解决冲突的泥潭之中。
- 系统发布效率低:任何模块变更都需要发布整个系统,而系统发布过程中需要多个模块之间制约较多,需要对比各种文件,任何一处出现问题都会导致发布失败,往往一次发布需要数十分钟甚至数小时。
- 系统可用性差:单体架构各个功能模块是作为一个服务部署,相互之间会互相影响,一些热点功能会耗尽系统资源,导致其它服务低可用。
在上述问题中,前两点相信大家在实战过程中应该深有体会。对于第三点系统可用性问题,很多同学可能感触不深。接下来我们就通过黑马商城这个项目,给大家做一个简单演示。
首先,我们修改hm-service模块下的com.hmall.controller.HelloController
中的hello
方法,模拟方法执行时的耗时:
接下来,启动项目,目前有两个接口是无需登录即可访问的:
http://localhost:8080/hi
http://localhost:8080/search/list
经过测试,目前/search/list
是比较正常的,访问耗时在30毫秒左右。
接下来,我们假设/hi
这个接口是一个并发较高的热点接口,我们通过Jemeter来模拟500个用户不停访问。在课前资料中已经提供了Jemeter的测试脚本:
导入Jemeter并测试:
这个脚本会开启500个线程并发请求http://localhost/hi
这个接口。由于该接口存在执行耗时(500毫秒),这就服务端导致每秒能处理的请求数量有限,最终会有越来越多请求积压,直至Tomcat资源耗尽。这样,其它本来正常的接口(例如/search/list
)也都会被拖慢,甚至因超时而无法访问了。
我们测试一下,启动测试脚本,然后在浏览器访问http://localhost:8080/search/list
这个接口,会发现响应速度非常慢:
如果进一步提高/hi
这个接口的并发,最终会发现/search/list
接口的请求响应速度会越来越慢。
可见,单体架构的可用性是比较差的,功能之间相互影响比较大。
当然,有同学会说我们可以做水平扩展。
此时如果我们对系统做水平扩展,增加更多机器,资源还是会被这样的热点接口占用,从而影响到其它接口,并不能从根本上解决问题。这也就是单体架构的扩展性差的一个原因。
而要想解决这些问题,就需要使用微服务架构了。
1.2.微服务
微服务架构,首先是服务化,就是将单体架构中的功能模块从单体应用中拆分出来,独立部署为多个服务。同时要满足下面的一些特点:
- 单一职责:一个微服务负责一部分业务功能,并且其核心数据不依赖于其它模块。
- 团队自治:每个微服务都有自己独立的开发、测试、发布、运维人员,团队人员规模不超过10人(2张披萨能喂饱)
- 服务自治:每个微服务都独立打包部署,访问自己独立的数据库。并且要做好服务隔离,避免对其它服务产生影响
例如,黑马商城项目,我们就可以把商品、用户、购物车、交易等模块拆分,交给不同的团队去开发,并独立部署:
那么,单体架构存在的问题有没有解决呢?
- 团队协作成本高?
-
- 由于服务拆分,每个服务代码量大大减少,参与开发的后台人员在1~3名,协作成本大大降低
- 系统发布效率低?
-
- 每个服务都是独立部署,当有某个服务有代码变更时,只需要打包部署该服务即可
- 系统可用性差?
-
- 每个服务独立部署,并且做好服务隔离,使用自己的服务器资源,不会影响到其它服务。
综上所述,微服务架构解决了单体架构存在的问题,特别适合大型互联网项目的开发,因此被各大互联网公司普遍采用。大家以前可能听说过分布式架构,分布式就是服务拆分的过程,其实微服务架构正式分布式架构的一种最佳实践的方案。
当然,微服务架构虽然能解决单体架构的各种问题,但在拆分的过程中,还会面临很多其它问题。比如:
- 如果出现跨服务的业务该如何处理?
- 页面请求到底该访问哪个服务?
- 如何实现各个服务之间的服务隔离?
这些问题,我们在后续的学习中会给大家逐一解答。
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 |
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) |
2.2.x, 2.3.x (Starting with SR5) |
|
2.1.x |
|
2.0.x |
|
1.5.x |
|
1.5.x |
因此,我们推荐使用次新版本:Spring Cloud 2021.0.x以及Spring Boot 2.7.x版本。
另外,Aliba