微服务部署
部署流程
一、本地部署
- 梳理服务部署表格
- Maven 子父模块打包
- Dockerfile 编写
- 编写环境依赖配置
- 编写服务配置
- 调整程序配置
- 测试访问
二、服务端部署
- 准备服务器
- Docker Compose 安装
- 同步文件
- 获取 jar 包
- 服务启动
- 测试访问
本地部署
1.1、梳理服务部署表格
在部署微服务项目前,首先要规划好要部署哪些服务、以及各服务的关键信息,比如服务名称、版本号、占用端口号、关键配置等。
对于我的在线判题项目,梳理好的服务表格如下:
服务名称 | 英文名 | 端口号 | 版本号 | 服务类别 |
---|---|---|---|---|
数据库 | mysql | 3306 | v8 | 环境依赖 |
缓存 | redis | 6379 | v6 | 环境依赖 |
消息队列 | rabbitmq | 5672, 15672 | v3.12.6 | 环境依赖 |
注册中心 | nacos | 8848 | v2.2.0 | 环境依赖 |
网关服务 | gateway | 8101 | java 8 | 业务服务 |
用户服务 | yuoj-backend-user-service | 8102 | java 8 | 业务服务 |
题目服务 | yuoj-backend-question-service | 8103 | java 8 | 业务服务 |
判题服务 | yuoj-backend-judge-service | 8104 | java 8 | 业务服务 |
为什么这里我要划分服务类别为 “环境依赖” 和 “业务服务” 呢?
因为在启动服务时,必须要先启动环境依赖,才能启动业务服务,否则就会报类似 “无法连接数据库” 之类的错误。
1.2、Maven 子父模块打包
对于微服务项目,我们通常是使用 Maven 的子父模块功能进行管理的。需要部署项目时,不用针对每个子服务单独执行 mvn package
命令进行打包,而是可以一键打包所有服务。
想要实现这个功能,需要给子父模块的依赖文件(pom.xml)进行一些配置,主要包括:
1)父模块配置
在父模块的 pom.xml 文件中引入 spring-boot-maven-plugin
即可,注意一定不要配置 configuration 和 repackage!
示例代码如下:
1 | <plugin> |
2)子模块配置
修改所有需要启动 Spring Boot 的服务(用户服务、题目服务、判题服务、网关服务)的子模块 pom.xml 文件。
主要是增加 executions 配置,使用 spring-boot-maven-plugin 的 repackage 命令来构建子模块,从而自动在构建时将公共模块的依赖打入 jar 包。
示例代码如下:
1 | <plugin> |
1.3、Dockerfile 编写
Dockerfile 是定义 Docker 容器镜像构建过程的文件,包括容器镜像使用的基础环境、容器内的依赖和文件、容器的配置、启动命令等。
有了 Dockerfile,我们就能很轻松地制作出自己的容器镜像。
虽然 Dockerfile 的写法并不复杂,但我还是建议大家尽量不要自己写,直接去网上找个差不多的项目,复制粘贴别人的 Dockerfile 就足够了!
这里鱼皮给大家提供 2 种常用的 Spring Boot 项目的 Dockerfile。
1)复制 jar 包版
思路:在本地打好 jar 包后,复制 jar 包到容器中运行
示例代码如下:
1 | # 基础镜像 |
2)Maven 打包版
思路:复制本地代码到容器中,在容器中使用 Maven 打包再运行
示例代码如下:
1 | # 基础镜像 |
此处由于我们的微服务项目可以一键打好所有子服务的 jar 包,就没必要每个服务单独在容器中打包了,所以选择第一种方式的 Dockerfile。
1.4、编写环境依赖配置
接下来,我们就要编写 Docker Compose 的配置文件了,可以根据配置文件快速启动多个服务。
之前我们已经梳理了服务部署表格,将服务划分为了 “环境依赖” 和 “业务服务”。
由于业务服务依赖 MySQL 等环境依赖,所以需要拆分 2 套 Docker Compose 的配置文件,分别为 docker-compose.env.yml
环境配置和 docker-compose.service.yml
业务服务配置,保证先成功启动依赖,再启动服务。
学过 Docker Compose 的同学可能听说过 depends_on 配置,也能决定服务的启动顺序。但是千万注意,depends_on 并不会等待服务完全就绪,只是确保它们在启动时的顺序,并不稳定。
如何编写 Docker Compose 文件呢?
和 Dockerfile 一样,直接去网上找现成的 Docker Compose file,复制粘贴过来略做修改就能使用了~
再配合以下 2 个网站,完全无需记忆 Docker Compose 的写法!
- Docker Compose file 官方文档:https://docs.docker.com/compose/compose-file/
- 搜索现成的 Docker 镜像:https://hub.docker.com/
1)MySQL
我们不仅要创建一个 MySQL 服务,还要在创建服务后自动创建我们需要的库表结构。
所以需要先准备数据库 SQL 脚本文件,里面包含了建库、建表语句,我们把它放在微服务项目根目录的 mysql-init
文件夹中:
鱼皮带大家做的每个项目都提供了现成的建表语句,这是一个非常好的开发习惯,便于其他人快速启动你的项目。
由于要在本地启动 MySQL,还需要定义一个文件夹 .mysql-data
来存放 MySQL 的持久化数据,防止容器重启后数据丢失。
做好这两点后,就可以编写 docker-compose.env.yml
文件了,先只写一个 MySQL 服务,示例代码如下:
关键配置的含义我都写到注释里了
1 | version: '3' |
写好配置文件后,可以直接在 IDEA 里执行 Docker Compose 文件,调试 MySQL 的运行:
运行成功后,我们可以在本地成功连接数据库:
2)Redis
Redis 服务的定义和启动操作和 MySQL 服务几乎一致,Redis 的 Docker Compose 配置示例代码如下:
1 | version: '3' |
然后在本地执行 Docker Compose 文件,启动 Redis 服务,并且尝试进入 Terminal 来调试 Redis:
3)RabbitMQ
同 MySQL 和 Redis,RabbitMQ 的 Docker Compose 配置示例代码如下:
1 | version: '3' |
本地执行 Docker Compose 文件,启动 RabbitMQ 服务,然后可以访问 localhost:15672
查看到管理面板,就表示启动成功了~
账号密码都是 guest
4)Nacos
和其他服务一样,Nacos 也需要编写 Docker Compose 配置。
但是在选择 Nacos 镜像时必须要注意,建议选择支持 linux/arm64 架构的镜像版本,比如 v2.2.0-slim
,否则后面可能会无法运行:
Nacos 示例配置文件如下:
1 | version: '3' |
然后在本地执行 Docker Compose 启动 Nacos,访问 localhost:8848/nacos
能够看到管理页面,就表示运行成功了~
管理页面的账号和密码默认都是 nacos
完整 Docker Compose 文件
分别调试完上述服务后,我们把所有的配置拼在一起,就得到了完整的文件,文件名为 docker-compose.env.yml
。
完整代码如下:
1 | version: '3' |
1.5、编写业务服务配置
用同样的方式,我们可以编写业务服务的 Docker Compose 文件,文件名称 docker-compose.service.yml
。
示例代码如下,其中需要格外关注的配置是 build 和 depends_on:
1 | version: '3' |
1.6、调整程序配置
编写好上述配置文件后,本地尝试运行 Docker Compose 业务服务,结果发现:报错啦!依赖服务的地址访问不通!
这是由于之前我们的项目访问依赖服务时,全部是使用了固定的 IP 地址(比如 localhost),而容器内部的 localhost(或 127.0.0.1)通常指向容器本身,而不是宿主主机。所以为了在容器内访问其他服务,程序中应该使用服务名称而不是 localhost。
我们给每个 Spring Boot 服务都增加一套 prod 上线配置,在配置中更改服务调用地址。
用户服务、题目服务和判题服务的 application-prod.yml
配置修改如下:
1 | # 生产环境配置文件 |
Gateway 网关服务的配置修改如下:
1 | spring: |
然后执行 mvn package
命令重新打包、执行 Docker Compose。
1.7、测试访问
修复上述问题后,所有服务都可以通过 Docker Compose 文件启动了。
然后我们访问 localhost:8101/doc.html
网关地址,能够看到 Swagger 聚合接口文档。
依次调用用户注册 => 登录 => 获取登录用户信息 => 创建题目接口,全部执行成功。
至此,第一阶段就完成啦。
服务器部署
2.1、准备服务器
首先,我们要有一台 Linux 服务器。
选择服务器前,我们必须要评估下微服务项目的内存占用,千万别把服务器的内存买小了!
可以使用 Docker Desktop 直接查看内存占用,虚拟机内存大概占用了 8 个 G、容器实际内存占用了 4 个 G:
那我们搞多少内存的服务器呢?
我猜很多同学会说 8 G,奈何我天生反骨,明知山有虎偏向虎山行(主要是想省 💰),我就搞一台 2 核 4 G 的服务器吧(发行版是 CentOS 7.9 Linux),咱们来猜一猜它够不够部署这套有 4 个业务服务的微服务项目呢?
咱们一起来见证下!
2.2、Docker Compose 安装
有了服务器后,直接参考 Docker Compose 官方文档来安装。这里我们使用 Docker Compose V2 版本,相比 V1 版本统一了命令,使用更方便:
Docker Compose V2 地址:https://docs.docker.com/compose/migrate/
Docker Compose Linux 安装:https://docs.docker.com/compose/install/linux/#install-using-the-repository
安装过程很简单,跟着官方文档来就行了,主要包括以下几个步骤:
1)设定安装来源:
1 | sudo yum install -y yum-utils |
2)安装 Docker 和 Docker Compose:
1 | sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin |
3)启动 Docker:
1 | sudo systemctl start docker |
4)测试 Docker:
1 | systemctl status docker |
2.3、同步文件
接下来,我们需要把本地折腾好的微服务项目源码上传到服务器上,可以选择用 FTP 或 SSH 连接文件手动上传文件。
我这里使用 JetBrains 开发工具的远程部署功能,可以配置文件自动上传,步骤如下:
1)进入远程部署配置
2)添加远程部署配置:
这里建议大家不要暴露自己的服务器 IP 啊,当你看到本文的时候,其实我已经把服务器的 IP 更换掉了哈哈哈哈哈哈哈哈!
3)指定连接的服务器配置:
4)配置本地文件和服务器文件路径映射:
5)开启自动上传:
6)首次需要手动上传文件。
上传前记得先删除无用的文件,然后右键项目根目录,点击部署上传代码:
上传成功,在服务器对应路径(/code/yuoj-backend-microservice)下能看到已上传的文件列表:
2.4、获取 jar 包
光把代码上传到服务器还是不够的,因为我们构建 Docker 镜像需要 jar 包。
有 2 种方式得到 jar 包:
- 本地执行
mvn package
打好 jar 包,然后再上传 - 服务器上装 Maven,在服务器上打包
但是因为 jar 包比较大,频繁改动的话同步速度会比较慢,所以更建议第二种方式,步骤如下:
1)安装 Maven:
1 | sudo yum install maven |
2)安装好后,执行打包:
1 | sudo mvn package |
打包成功:
2.5、服务启动
所有一切准备就绪,接下来就是使用 Docker Compose 命令分别启动环境依赖和业务服务啦。
1)启动环境依赖
先使用 docker compose 一行命令启动环境依赖:
1 | docker compose -f docker-compose.env.yml up |
注意:
- 老版本使用 “docker-compose” 替代 “docker compose”
- 如果没有权限,命令前加上 “sudo”
然后喝杯咖啡,等待启动即可~
启动成功后,我们可以通过公网 IP 来尝试访问服务。
先进入到云服务商的服务器配置页,修改服务器的防火墙配置,放通以下端口:
然后像访问本地服务一样分别去访问 MySQL、Redis、RabbitMQ、Nacos 即可,应该都是成功的。
由于进程在前台启动会影响我们的操作,所以先按 ctrl + c
退出,加上 -d
参数让容器在后台启动:
1 | sudo docker compose -f docker-compose.env.yml up -d |
试着查看下 docker 容器的状态:
1 | sudo docker stats |
能够查看到所有容器的资源占用情况:
实话说,我开始紧张了,不知道 4 G 的内存够不够撑。。。
2)启动业务服务
确保环境依赖都启动成功后,接下来启动业务服务:
1 | docker compose -f docker-compose.service.yml up |
项目全部启动,看得很爽:
正常来说,应该会启动成功;但如果运气背,可能会有失败,比如我这的网关服务就启动失败了。
如果某个服务启动失败,可以再次单独只启动它,比如网关服务:
1 | sudo docker compose -f docker-compose.service.yml up yuoj-backend-gateway |
2.6、测试访问
最后,像验证本地微服务项目部署一样,访问线上网关的接口文档( http://你的服务器 IP:8101/doc.html ),依次调用用户注册 => 登录 => 获取登录用户信息 => 创建题目,全部成功~
最后使用 docker stats
命令查看 Docker 容器的状态,发现总共的内存占用大概 3 G,也就是说 4 G 内存的服务器是完全足够小型微服务项目的部署了~
至此,微服务项目部署教程就结束了。