当前位置: 首页 > news >正文

保姆级微服务部署教程

大家好,我是鱼皮。

项目上线是每位学编程同学必须掌握的基本技能。之前我已经给大家分享过很多种上线单体项目的方法了,今天再出一期微服务项目的部署教程,用一种最简单的方法,带大家轻松部署微服务项目。

开始之前,先做个小调研啊,大家更喜欢看 “真实踩坑版” 的教程还是 “压缩纯净版” 的教程呢?

本期教程我还是保持自己一贯的风格,依然是保姆级教程,包含了一些踩坑过程和解决方案,大家跟着做就完事儿~

更推荐看视频版:https://www.bilibili.com/video/BV1Cp4y1F7eA/

项目介绍

这次的教程以我带大家全程直播手把手开发的、基于 Spring Cloud + Docker 代码沙箱的 在线判题系统 为例,进行演示。

这个项目的核心功能是让用户能够在线选题和做题,然后由系统自动判题:

项目用到的核心依赖包括:MySQL 数据库、Redis 缓存、RabbitMQ 消息队列、Nacos 注册中心

涉及的核心服务包括:用户服务、题目服务、判题服务(代码沙箱)、Gateway 网关服务

传统部署

对于这样一个项目,如果我们还用传统单机项目的部署方式,一个个打 jar 包、用 Java 命令来启动,会有哪些问题呢?

  1. 要一个个安装依赖,比如 MySQL 数据库、Redis、消息队列、Nacos,非常麻烦!
  2. 要一个个打 jar 包、一个个手动运行 jar 包,非常麻烦!
  3. 不方便集中观察所有服务的运行状态和资源占用情况

所以,为了解决这些问题,我们会选用一种更高效的微服务部署方式 —— Docker Compose。

Docker Compose 介绍

在介绍 Docker Compose 前,先简单介绍下 Docker。

Docker 是一种容器技术,允许开发者将应用程序和所有依赖项(如代码、库、配置等)制作为 镜像。可以把镜像简单理解为软件安装包,可以在不同的计算机上通过它快速安装和启动应用程序(容器),这些程序独立隔离地运行,不受外部环境的影响。

如果要部署微服务项目,可能要启动多个 Docker 容器,比如 MySQL 容器、用户服务容器等。这时就需要 Docker Compose 了。它是一个容器编排助手,用于集中管理多个 Docker 容器的启动和协同工作。可以在一个配置文件中集中定义所有容器以及它们的关系。然后,可以使用一行命令启动所有容器,而不需要手动运行多个命令。

需要注意的是,Docker Compose 通常适用于把所有微服务部署在同一台服务器的场景,在真实的企业级项目中,往往会使用 K8S 等更专业的容器编排和自动化部署工具,更方便地在多个服务器上部署容器。

部署流程

了解了 Docker 和 Docker Compose 的作用后,我们来快速了解下部署流程,分为 2 大阶段 —— 本地部署和服务器部署。

一、本地部署

  1. 梳理服务部署表格
  2. Maven 子父模块打包
  3. Dockerfile 编写
  4. 编写环境依赖配置
  5. 编写服务配置
  6. 调整程序配置
  7. 测试访问

二、服务端部署

  1. 准备服务器
  2. Docker Compose 安装
  3. 同步文件
  4. 获取 jar 包
  5. 服务启动
  6. 测试访问

一、本地部署

第一阶段是本地部署,也可以叫做部署准备。

强烈建议大家,比起直接操作线上服务器,最好是先在本地把所有的流程跑通,风险更低、效率更高。

这里我使用的是 Mac 操作系统,已经安装了 Docker Desktop 软件,管理 Docker 容器会更方便一些。

对于本地没有 Docker 环境的同学,这一阶段仔细看一遍有个印象就足够了。可以直接拿我调试好的配置文件在服务器上部署,而不用自己调试。

怎么样,够贴心吧!可以叫我 “保姆鱼皮”,简称 “保姆皮”。

1.1、梳理服务部署表格

在部署微服务项目前,首先要规划好要部署哪些服务、以及各服务的关键信息,比如服务名称、版本号、占用端口号、关键配置等。

对于我的在线判题项目,梳理好的服务表格如下:

服务名称英文名端口号版本号服务类别
数据库mysql3306v8环境依赖
缓存redis6379v6环境依赖
消息队列rabbitmq5672, 15672v3.12.6环境依赖
注册中心nacos8848v2.2.0环境依赖
网关服务gateway8101java 8业务服务
用户服务yuoj-backend-user-service8102java 8业务服务
题目服务yuoj-backend-question-service8103java 8业务服务
判题服务yuoj-backend-judge-service8104java 8业务服务

为什么这里我要划分服务类别为 “环境依赖” 和 “业务服务” 呢?

因为在启动服务时,必须要先启动环境依赖,才能启动业务服务,否则就会报类似 “无法连接数据库” 之类的错误。

1.2、Maven 子父模块打包

对于微服务项目,我们通常是使用 Maven 的子父模块功能进行管理的。需要部署项目时,不用针对每个子服务单独执行 mvn package 命令进行打包,而是可以一键打包所有服务。

想要实现这个功能,需要给子父模块的依赖文件(pom.xml)进行一些配置,主要包括:

1)父模块配置

在父模块的 pom.xml 文件中引入 spring-boot-maven-plugin 即可,注意一定不要配置 configuration 和 repackage!

示例代码如下:

<plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring-boot.version}</version>
</plugin>
2)子模块配置

修改所有需要启动 Spring Boot 的服务(用户服务、题目服务、判题服务、网关服务)的子模块 pom.xml 文件。

主要是增加 executions 配置,使用 spring-boot-maven-plugin 的 repackage 命令来构建子模块,从而自动在构建时将公共模块的依赖打入 jar 包。

示例代码如下:

<plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><executions><execution><id>repackage</id><goals><goal>repackage</goal></goals></execution></executions>
</plugin>

1.3、Dockerfile 编写

Dockerfile 是定义 Docker 容器镜像构建过程的文件,包括容器镜像使用的基础环境、容器内的依赖和文件、容器的配置、启动命令等。

有了 Dockerfile,我们就能很轻松地制作出自己的容器镜像。

虽然 Dockerfile 的写法并不复杂,但我还是建议大家尽量不要自己写,直接去网上找个差不多的项目,复制粘贴别人的 Dockerfile 就足够了!

这里鱼皮给大家提供 2 种常用的 Spring Boot 项目的 Dockerfile。

1)复制 jar 包版

思路:在本地打好 jar 包后,复制 jar 包到容器中运行

示例代码如下:

# 基础镜像
FROM openjdk:8-jdk-alpine# 指定工作目录
WORKDIR /app# 将 jar 包添加到工作目录,比如 target/yuoj-backend-user-service-0.0.1-SNAPSHOT.jar
ADD {本地 jar 包路径} . # 暴露端口
EXPOSE {服务端口号}# 启动命令
ENTRYPOINT ["java","-jar","/app/{jar 包名称}","--spring.profiles.active=prod"]
2)Maven 打包版

思路:复制本地代码到容器中,在容器中使用 Maven 打包再运行

示例代码如下:

# 基础镜像
FROM maven:3.8.1-jdk-8-slim as builder# 指定工作目录
WORKDIR /app# 添加源码文件
COPY pom.xml .
COPY src ./src# 构建 jar 包,跳过测试
RUN mvn package -DskipTests# 启动命令
ENTRYPOINT ["java","-jar","/app/target/{jar 包名称}","--spring.profiles.active=prod"]

此处由于我们的微服务项目可以一键打好所有子服务的 jar 包,就没必要每个服务单独在容器中打包了,所以选择第一种方式的 Dockerfile。

我们需要给每个 Spring Boot 服务(用户服务、题目服务、判题服务、网关服务)都编写一个 Dockerfile,放到每个子服务的根目录下。

以用户服务为例,示例代码如下:

# 基础镜像
FROM openjdk:8-jdk-alpine# 指定工作目录
WORKDIR /app# 将 jar 包添加到工作目录,比如 target/yuoj-backend-user-service-0.0.1-SNAPSHOT.jar
ADD target/yuoj-backend-user-service-0.0.1-SNAPSHOT.jar .# 暴露端口
EXPOSE 8102# 启动命令
ENTRYPOINT ["java","-jar","/app/yuoj-backend-user-service-0.0.1-SNAPSHOT.jar","--spring.profiles.active=prod"]

建议先在本地利用 IDEA 开发工具调通镜像构建流程,确保每个 Dockerfile 都是可以成功制作镜像的:

查看容器的启动日志,发现能够启动服务、看到 Spring 图标即可:

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/

当然,现在 AI 时代了,还有更简单的方式!

直接把我们整理好的服务部署需要喂给 GPT,让 AI 帮我们生成配置即可~

示例 prompt:

现在我需要用 docker compose 来部署 mysql 8(3306 端口)username=root,password=123456
redis 6(无密码,6379端口)、rabbitmq v.3.12.6( 5672 端口   password: guest,username: guest)、nacos 2.2.0(8848端口);还有 4 个本地的 springboot 服务(名称分别为:yuoj-backend-user-service 8102端口、yuoj-backend-question-service 8103端口、yuoj-backend-judge-service 8104端口、yuoj-backend-gateway 8101 端口),每个服务本地目录都有一个 Dockerfile,请帮我自动生成 docker compose 的 yml 配置文件,要求这些服务网络能够连通

效果还是非常不错的,只要你描述地足够清楚,生成的配置完全可用!

由于这篇文章是教程嘛,我就带大家通过调试的方式一步步完成 Docker Compose 文件,最后会把完整的 Docker Compose 文件给大家分享出来,大家直接用就行了~

我们要分别在 Docker Compose 中定义 4 大基础依赖,包括 MySQL、Redis、RabbitMQ 和 Nacos。

1)MySQL

我们不仅要创建一个 MySQL 服务,还要在创建服务后自动创建我们需要的库表结构。

所以需要先准备数据库 SQL 脚本文件,里面包含了建库、建表语句,我们把它放在微服务项目根目录的 mysql-init 文件夹中:

鱼皮带大家做的每个项目都提供了现成的建表语句,这是一个非常好的开发习惯,便于其他人快速启动你的项目。

由于要在本地启动 MySQL,还需要定义一个文件夹 .mysql-data 来存放 MySQL 的持久化数据,防止容器重启后数据丢失。

做好这两点后,就可以编写 docker-compose.env.yml 文件了,先只写一个 MySQL 服务,示例代码如下:

关键配置的含义我都写到注释里了

version: '3'
services:mysql:image: mysql:8 # 使用的镜像container_name: yuoj-mysql # 启动的实例名称environment:MYSQL_ROOT_PASSWORD: 123456 # root 用户密码ports:- "3306:3306" # 端口映射volumes:- ./.mysql-data:/var/lib/mysql # 将数据目录挂载到本地目录以进行持久化- ./mysql-init:/docker-entrypoint-initdb.d # 自动执行启动脚本restart: always # 崩溃后自动重启networks:- mynetwork # 指定网络
networks:mynetwork: # 自定义网络,实现网络互通和隔离

写好配置文件后,可以直接在 IDEA 里执行 Docker Compose 文件,调试 MySQL 的运行:

运行成功后,我们可以在本地成功连接数据库:

2)Redis

Redis 服务的定义和启动操作和 MySQL 服务几乎一致,Redis 的 Docker Compose 配置示例代码如下:

version: '3'
services:redis:image: redis:6container_name: yuoj-redisports:- "6379:6379"networks:- mynetworkvolumes:- ./.redis-data:/data # 持久化
networks:mynetwork:

然后在本地执行 Docker Compose 文件,启动 Redis 服务,并且尝试进入 Terminal 来调试 Redis:

3)RabbitMQ

同 MySQL 和 Redis,RabbitMQ 的 Docker Compose 配置示例代码如下:

version: '3'
services:rabbitmq:image: rabbitmq:3.12.6-management # 支持管理面板的消息队列container_name: yuoj-rabbitmqenvironment:RABBITMQ_DEFAULT_USER: guestRABBITMQ_DEFAULT_PASS: guestports:- "5672:5672"- "15672:15672" # RabbitMQ Dashboard 端口volumes:- ./.rabbitmq-data:/var/lib/rabbitmq # 持久化networks:- mynetwork
networks:mynetwork:

本地执行 Docker Compose 文件,启动 RabbitMQ 服务,然后可以访问 localhost:15672 查看到管理面板,就表示启动成功了~

账号密码都是 guest

4)Nacos

和其他服务一样,Nacos 也需要编写 Docker Compose 配置。

但是在选择 Nacos 镜像时必须要注意,建议选择支持 linux/arm64 架构的镜像版本,比如 v2.2.0-slim,否则后面可能会无法运行:

Nacos 示例配置文件如下:

version: '3'
services:nacos:image: nacos/nacos-server:v2.2.0-slimcontainer_name: yuoj-nacosports:- "8848:8848"volumes:- ./.nacos-data:/home/nacos/datanetworks:- mynetworkenvironment:- MODE=standalone # 单节点模式启动- PREFER_HOST_MODE=hostname # 支持 hostname- TZ=Asia/Shanghai # 控制时区
networks:mynetwork:

然后在本地执行 Docker Compose 启动 Nacos,访问 localhost:8848/nacos 能够看到管理页面,就表示运行成功了~

管理页面的账号和密码默认都是 nacos

完整 Docker Compose 文件

分别调试完上述服务后,我们把所有的配置拼在一起,就得到了完整的文件,文件名为 docker-compose.env.yml

完整代码如下:

version: '3'
services:mysql:image: mysql:8 # 使用的镜像container_name: yuoj-mysql # 启动的实例名称environment:MYSQL_ROOT_PASSWORD: 123456 # root 用户密码ports:- "3306:3306" # 端口映射volumes:- ./.mysql-data:/var/lib/mysql # 将数据目录挂载到本地目录以进行持久化- ./mysql-init:/docker-entrypoint-initdb.d # 启动脚本restart: always # 崩溃后自动重启networks:- mynetwork # 指定网络redis:image: redis:6container_name: yuoj-redisports:- "6379:6379"networks:- mynetworkvolumes:- ./.redis-data:/data # 持久化rabbitmq:image: rabbitmq:3.12.6-management # 支持管理面板的消息队列container_name: yuoj-rabbitmqenvironment:RABBITMQ_DEFAULT_USER: guestRABBITMQ_DEFAULT_PASS: guestports:- "5672:5672"- "15672:15672" # RabbitMQ Dashboard 端口volumes:- ./.rabbitmq-data:/var/lib/rabbitmq # 持久化networks:- mynetworknacos:image: nacos/nacos-server:v2.2.0-slimcontainer_name: yuoj-nacosports:- "8848:8848"volumes:- ./.nacos-data:/home/nacos/datanetworks:- mynetworkenvironment:- MODE=standalone # 单节点模式启动- PREFER_HOST_MODE=hostname # 支持 hostname- TZ=Asia/Shanghai # 控制时区
networks:mynetwork:

1.5、编写业务服务配置

用同样的方式,我们可以编写业务服务的 Docker Compose 文件,文件名称 docker-compose.service.yml

示例代码如下,其中需要格外关注的配置是 build 和 depends_on:

version: '3'
services:yuoj-backend-gateway:container_name: yuoj-backend-gatewaybuild: # 服务的 Docker 构建文件位置context: ./yuoj-backend-gatewaydockerfile: Dockerfileports:- "8101:8101"networks:- mynetworkyuoj-backend-user-service:container_name: yuoj-backend-user-servicebuild:context: ./yuoj-backend-user-servicedockerfile: Dockerfileports:- "8102:8102"networks:- mynetworkdepends_on: # 本服务依赖的服务,控制启动先后顺序- yuoj-backend-gatewayyuoj-backend-question-service:container_name: yuoj-backend-question-servicebuild:context: ./yuoj-backend-question-servicedockerfile: Dockerfileports:- "8103:8103"networks:- mynetworkdepends_on:- yuoj-backend-user-service- yuoj-backend-gatewayyuoj-backend-judge-service:container_name: yuoj-backend-judge-servicebuild:context: ./yuoj-backend-judge-servicedockerfile: Dockerfileports:- "8104:8104"networks:- mynetworkdepends_on:- yuoj-backend-user-service- yuoj-backend-question-service- yuoj-backend-gateway# 网络,不定义的话就是默认网络
networks:mynetwork:

1.6、调整程序配置

编写好上述配置文件后,本地尝试运行 Docker Compose 业务服务,结果发现:报错啦!依赖服务的地址访问不通!

这是由于之前我们的项目访问依赖服务时,全部是使用了固定的 IP 地址(比如 localhost),而容器内部的 localhost(或 127.0.0.1)通常指向容器本身,而不是宿主主机。所以为了在容器内访问其他服务,程序中应该使用服务名称而不是 localhost。

我们给每个 Spring Boot 服务都增加一套 prod 上线配置,在配置中更改服务调用地址。

用户服务、题目服务和判题服务的 application-prod.yml 配置修改如下:

# 生产环境配置文件
spring:# 数据库配置datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://mysql:3306/yuoj # localhost 改为 mysqlusername: rootpassword: 123456# Redis 配置redis:database: 1host: redis # localhost 改为 redisport: 6379timeout: 5000cloud:nacos:discovery:server-addr: nacos:8848 # localhost 改为 nacosrabbitmq:host: rabbitmq # localhost 改为 rabbitmqport: 5672password: guestusername: guest

Gateway 网关服务的配置修改如下:

spring:cloud:nacos:discovery:server-addr: nacos:8848 # localhost 改为 nacosgateway:routes:- id: yuoj-backend-user-serviceuri: lb://yuoj-backend-user-servicepredicates:- Path=/api/user/**- id: yuoj-backend-question-serviceuri: lb://yuoj-backend-question-servicepredicates:- Path=/api/question/**- id: yuoj-backend-judge-serviceuri: lb://yuoj-backend-judge-servicepredicates:- Path=/api/judge/**application:name: yuoj-backend-gatewaymain:web-application-type: reactive
server:port: 8101
knife4j:gateway:enabled: truestrategy: discoverdiscover:enabled: trueversion: swagger2

然后执行 mvn package 命令重新打包、执行 Docker Compose。

结果发现大多数服务都启动了,但是判题服务还有报错。

这是因为程序在创建消息队列时存在硬编码的变量,指定了 host 为 “localhost”,示例代码如下:

ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
String EXCHANGE_NAME = "code_exchange";
channel.exchangeDeclare(EXCHANGE_NAME, "direct");

举这个例子是为了告诉大家,在程序中尽量不要写固定 IP 或域名,全部改为动态读取配置文件,便于修改。

示例修改后的代码如下:

/*** 用于创建测试程序用到的交换机和队列(只用在程序启动前执行一次)*/
@Slf4j
@Component
public class InitRabbitMqBean {@Value("${spring.rabbitmq.host:localhost}")private String host;@PostConstructpublic void init() {try {ConnectionFactory factory = new ConnectionFactory();factory.setHost(host);Connection connection = factory.newConnection();Channel channel = connection.createChannel();String EXCHANGE_NAME = "code_exchange";channel.exchangeDeclare(EXCHANGE_NAME, "direct");// 创建队列,随机分配一个队列名称String queueName = "code_queue";channel.queueDeclare(queueName, true, false, false, null);channel.queueBind(queueName, EXCHANGE_NAME, "my_routingKey");log.info("消息队列启动成功");} catch (Exception e) {log.error("消息队列启动失败");}}
}

1.7、测试访问

修复上述问题后,所有服务都可以通过 Docker Compose 文件启动了。

然后我们访问 localhost:8101/doc.html 网关地址,能够看到 Swagger 聚合接口文档。

依次调用用户注册 => 登录 => 获取登录用户信息 => 创建题目接口,全部执行成功。

至此,第一阶段就完成啦。

二、服务器部署

在第二阶段,我们的目标就是在真实的 Linux 服务器上部署微服务项目。有了第一阶段的准备,第二阶段简直可以说是易如反掌!

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)设定安装来源:

sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

2)安装 Docker 和 Docker Compose:

sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

3)启动 Docker:

sudo systemctl start docker

4)测试 Docker:

systemctl status docker
sudo docker run hello-world

2.3、同步文件

接下来,我们需要把本地折腾好的微服务项目源码上传到服务器上,可以选择用 FTP 或 SSH 连接文件手动上传文件。

我这里使用 JetBrains 开发工具的远程部署功能,可以配置文件自动上传,步骤如下:

1)进入远程部署配置

2)添加远程部署配置:

这里建议大家不要暴露自己的服务器 IP 啊,当你看到本文的时候,其实我已经把服务器的 IP 更换掉了哈哈哈哈哈哈哈哈!

3)指定连接的服务器配置:

4)配置本地文件和服务器文件路径映射:

5)开启自动上传:

6)首次需要手动上传文件。

上传前记得先删除无用的文件,然后右键项目根目录,点击部署上传代码:

上传成功,在服务器对应路径(/code/yuoj-backend-microservice)下能看到已上传的文件列表:

2.4、获取 jar 包

光把代码上传到服务器还是不够的,因为我们构建 Docker 镜像需要 jar 包。

有 2 种方式得到 jar 包:

  1. 本地执行 mvn package 打好 jar 包,然后再上传
  2. 服务器上装 Maven,在服务器上打包

但是因为 jar 包比较大,频繁改动的话同步速度会比较慢,所以更建议第二种方式,步骤如下:

1)安装 Maven:

sudo yum install maven

2)安装好后,执行打包:

sudo mvn package

打包成功:

2.5、服务启动

所有一切准备就绪,接下来就是使用 Docker Compose 命令分别启动环境依赖和业务服务啦。

1)启动环境依赖

先使用 docker compose 一行命令启动环境依赖:

docker compose -f docker-compose.env.yml up

注意:

  1. 老版本使用 “docker-compose” 替代 “docker compose”
  2. 如果没有权限,命令前加上 “sudo”

然后喝杯咖啡,等待启动即可~

启动成功后,我们可以通过公网 IP 来尝试访问服务。

先进入到云服务商的服务器配置页,修改服务器的防火墙配置,放通以下端口:

然后像访问本地服务一样分别去访问 MySQL、Redis、RabbitMQ、Nacos 即可,应该都是成功的。

由于进程在前台启动会影响我们的操作,所以先按 ctrl + c 退出,加上 -d 参数让容器在后台启动:

sudo docker compose -f docker-compose.env.yml up -d

试着查看下 docker 容器的状态:

sudo docker stats

能够查看到所有容器的资源占用情况:

实话说,我开始紧张了,不知道 4 G 的内存够不够撑。。。

2)启动业务服务

确保环境依赖都启动成功后,接下来启动业务服务:

docker compose -f docker-compose.service.yml up

项目全部启动,看得很爽:

正常来说,应该会启动成功;但如果运气背,可能会有失败,比如我这的网关服务就启动失败了。

如果某个服务启动失败,可以再次单独只启动它,比如网关服务:

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 内存的服务器是完全足够小型微服务项目的部署了~

至此,微服务项目部署教程就结束了。

最后

最后我再问个问题,如果我只有一台 2 G 内存的服务器,能否成功部署这套有 4 个业务服务的项目呢?如果能的话,又应该怎么部署呢?欢迎大家讨论。

下图是个小提示:

终于写完了这篇 6000 多字的教程,如果觉得本期内容有帮助的话,也欢迎点赞、收藏三连支持,谢谢大家!

相关文章:

保姆级微服务部署教程

大家好&#xff0c;我是鱼皮。 项目上线是每位学编程同学必须掌握的基本技能。之前我已经给大家分享过很多种上线单体项目的方法了&#xff0c;今天再出一期微服务项目的部署教程&#xff0c;用一种最简单的方法&#xff0c;带大家轻松部署微服务项目。 开始之前&#xff0c;…...

springboot 定时任务

springboot 定时任务 在Spring Boot中&#xff0c;你可以使用Spring的Scheduled注解来创建定时任务。以下是一个简单的示例&#xff1a; 首先&#xff0c;你需要在Spring Boot的主类上添加EnableScheduling注解以启用定时任务功能。 import org.springframework.boot.Spring…...

【大数据】HBase入门指南

原创不易&#xff0c;注重版权。转载请注明原作者和原文链接 文章目录 HBase特性Hadoop的限制基本概念NameSpaceTableRowKeyColumnTimeStampCell 存储结构HBase 数据访问形式架构体系HBase组件HBase读写流程读流程写流程 MemStore Flush参数说明 StoreFile Compaction参数说明触…...

零售数据分析模板鉴赏-品类销售结构报表

不管是服装零售&#xff0c;还是连锁超市或者其他&#xff0c;只要是零售行业就绕不过商品数据分析&#xff0c;那么商品数据分析该怎么做&#xff1f;奥威BI的零售数据分析方案早早就预设好相关报表模板&#xff0c;点击应用后&#xff0c;一键替换数据源&#xff0c;立得新报…...

竞赛 深度学习 机器视觉 车位识别车道线检测 - python opencv

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习 机器视觉 车位识别车道线检测 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f947;学长这里给一个题目综合评分(每项满分5分) …...

MySQL中使用函数会使索引失效?

文章目录 1、前置准备2、ChatGPT的答案3、实践证明SQL1SQL2SQL3SQL4SQL5 4、总结 1、前置准备 首先创建我们要测试的库表 CREATE TABLE lianhe_index (id int(11) NOT NULL AUTO_INCREMENT COMMENT id,name varchar(255) DEFAULT NULL,age int(11) DEFAULT NULL,number int(1…...

金和OA C6任意文件读取漏洞 复现[附POC]

文章目录 金和OA C6任意文件读取漏洞 复现[附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 金和OA C6任意文件读取漏洞 复现[附POC] 0x01 前言 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试…...

IP地址技术原理

IP地址是互联网中的关键元素&#xff0c;它允许数据在全球范围内进行路由和传输。本文将深入探讨IP地址的技术原理&#xff0c;包括IP地址的结构、IP地址分配、子网划分和IPv4与IPv6之间的转换。 第一部分&#xff1a;IP地址基础 1.1IP地址是什么&#xff1f; IP地址&#xf…...

【网络安全】密码学基础

前言 密码学是网络安全的核心组成部分&#xff0c;它帮助我们保护信息&#xff0c;防止未经授权的访问。在这篇文章中&#xff0c;我们将从基础开始&#xff0c;深入了解密码学的基本概念和原理&#xff0c;包括加密、解密、密钥、哈希函数等。我们将尽可能使用简单的语言和实…...

AWS AD Connector 的网络配置

配置 AWS 的 AD Connector 通常遇到的都是些网络问题,且 AD Connector 本身屏蔽了一些网络细节,使得查找root cause往往有点困难,本文就把 AD Connector 网络问题梳理一下。 首先,需要搞清楚的是:AD Connector 是 Microsoft Active Directory 的一种代理,IAM可以通过它联…...

kafka详解(三)

2.2 Kafka命令行操作 2.2.1 主题命令行操作 1&#xff09;查看操作主题命令参数 [aahadoop102 kafka]$ bin/kafka-topics.sh2&#xff09;查看当前服务器中的所有topic (配置了环境变量不需要写bin/) [aahadoop102 kafka]$ bin/kafka-topics.sh --bootstrap-server hadoop10…...

[Spring] SpringMVC 简介(二)

目录 五、域对象共享数据 1、使用 ServletAPI 向 request 域对象共享数据 2、使用 ModelAndView 向 request 域对象共享数据 3、使用 Model、Map、ModelMap 向 request 域对象共享数据 4、向 session 域和 application 域共享数据 六、SpringMVC 的视图 1、ThymeleafVie…...

idea一些不太常用但是能提升编码效率的快捷键

Ctrl Shift V&#xff1a;从历史选择粘贴 从历史剪粘版中选择要粘贴的内容。Ctrl Shift Z&#xff1a;重做 恢复上一步撤销内容Shift F4&#xff1a;在新窗口中打开 比如要从另一个类中复制代码 可以把这个类在新窗口单独打开 用AltTab 来回切换复制Ctrl PageUp&#xff…...

vsto word属性信息 并读取

要通过VSTO (Visual Studio Tools for Office) 读取和操作 Microsoft Word 文档的属性信息&#xff0c;您可以使用 C# 或 VB.NET 等 .NET 编程语言结合 VSTO 来实现。以下是一个示例&#xff0c;演示如何获取 Word 文档的属性信息&#xff1a;首先&#xff0c;确保您已经在 Vis…...

android之TextView自由选择复制

文章目录 前言一、效果图二、实现步骤1.OnSelectListener2.SelectionInfo类3.TextLayoutUtil类4.复制弹框的xml布局5.弹框背景Drawable6.倒三角Drawable7.复制工具类8.调用 总结 前言 根据时代进步&#xff0c;那些干产品的也叼砖起来了&#xff0c;今天就遇到一个需求&#x…...

【mysql】 bash: mysql: command not found

在linux 服务器上安装了mysql 也可以正常运行。 但是执行命令&#xff0c;系统提示&#xff1a;bash: mysql: command not found bash:mysql:找不到命令 执行的命令是&#xff1a; mysql -u root -h 127.0.0.1 -p由于系统默认会查找的 /usr/bin/ 中下的命令&#xff0c;如…...

鲲山科技:引入和鲸 ModelWhale,实现量化策略的高效迭代

量化投资是数据科学在金融行业的应用。 2023 年&#xff0c;量化行业的超额收益开始收敛&#xff0c;量化私募如何形成自身核心竞争力&#xff1f; 和鲸拜访客户鲲山科技&#xff08;深圳&#xff09;&#xff0c;揭示其“弯道超车”的独家秘诀。 群体作战 年初至今&#xff…...

PFSK152 3BSE018877R1 有源滤波器的定义

PFSK152 3BSE018877R1 有源滤波器的定义 有源滤波器是以晶体管和运算放大器为基本元件设计的滤波电路。除了这些元件&#xff0c;有源滤波器的电路还包含电阻和电容&#xff0c;但不包含电感。 我们知道滤波器具有频率选择性。因此&#xff0c;有源滤波器电路使用晶体管和运算…...

WebDAV之π-Disk派盘 + 恒星播放器

想要拥有一款万能视频播放器,全能解码播放器,无需转码,支持所有格式的视频和音频,直接播放的播放器?那就选恒星播放器。 恒星播放器支持视频投屏,倍速播放,后台播放等功能,还能一键截图和录制gif动图。支持全格式超高清真4K解码,蓝光HDR低占用,支持ISO文件直出的播放…...

亚马逊,速卖通,敦煌产品测评补单攻略:低成本、高安全实操指南

随着电商平台的发展和消费者对产品质量的要求提升&#xff0c;测评补单成为了商家们提升销售和用户口碑的关键环节。然而&#xff0c;如何在保持成本低廉的同时确保操作安全&#xff0c;一直是卖家们面临的挑战。今天林哥分享一些实用的技巧和策略&#xff0c;帮助卖家们产品的…...

常用linux解压命令

1. 超过4g的zip文件在linux下unzip失败。需要用7z压缩&#xff0c;然后用p7zip命令解压。 p7zip -d x.7z 2. gzip解压.gz文件 gzip -d a11.txt.gz 和 gunzip a1.txt.gz gunzip –c filename.gz > filename #解压缩保留源文件, 上述命令非常容易写错&#xff0c;最后导…...

TensorFlow入门(二十二、梯度下降)

梯度下降的定义及作用 梯度下降本身是一个最优化算法,通常也被称为最速下降法。常被用于机器学习和人工智能中递归性地逼近最小偏差模型,也就是使用它找到一个函数的局部极小值。 使用过程中,梯度下降算法以函数上当前点对于梯度(或者是近似梯度)反方向的规定步长距离点进行迭代…...

WPF中的多重绑定

MultiBinding 将会给后端传回一个数组, 其顺序为绑定的顺序. 例如: <DataGridMargin"10"AutoGenerateColumns"False"ItemsSource"{Binding Stu}"><DataGrid.Columns><DataGridTextColumn Binding"{Binding Id}" Header…...

区块链在游戏行业的应用

区块链技术在游戏行业有许多潜在的应用&#xff0c;它可以改变游戏开发、发行和玩家交互的方式。以下是区块链技术在游戏行业的一些主要应用&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.游戏资产…...

uniapp快速入门系列(4)- 微信小程序开发

第四章 微信小程序开发 4.1 微信小程序开发与uniapp的融合4.2 微信小程序API在uniapp中的使用4.3 微信小程序常见问题的解决方法问题1: 如何获取用户信息&#xff1f;问题2: 如何获取当前位置&#xff1f;问题3: 如何发送网络请求&#xff1f; 在本章中&#xff0c;我们将学习如…...

Kafka保证消息幂等以及解决方案

1、幂等的基本概念 幂等简单点讲&#xff0c;就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的&#xff0c;不会产生任何副作用。幂等分很多种&#xff0c;比如接口的幂等、消息的幂等&#xff0c;它是分布式系统设计时必须要考虑的一个方面。 查询操作(天然幂等…...

接口测试用例设计

接口测试...

wireshark抓rtp包,提取出H265裸流数

调试rtsp收发流时&#xff0c;经常会需要抓包以确认是网络问题还是程序问题还是其它问题。通过tcpdump或者wireshark抓到的包通常是rtp流&#xff0c;保存为.pcap格式文件后中&#xff0c;可通过wireshark进行解析&#xff0c;得出h264裸流&#xff0c;并保存为文件。 1.wires…...

Excel往Word复制表格时删除空格

1.背景 在编写文档&#xff0c;经常需要从Excel往Word里复制表格 但是复制过去的表格前面会出现空格&#xff08;缩进&#xff09; 再WPS中试了很多方法&#xff0c;终于摆脱了挨个删除的困扰 2. WPS排版中删除 选择表格菜单栏-选在【开始】-【排版】选择【更多段落处理】-【段…...

客户机操作系统已禁用 CPU。请关闭或重置虚拟机(解决)

解决&#xff1a; 关闭虚拟机进入设置点击处理器给虚拟化引擎两个勾上确认后重新即可...